objc-msg-arm.s 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. /*
  2. * @APPLE_LICENSE_HEADER_START@
  3. *
  4. * Copyright (c) 1999-2007 Apple Computer, Inc. All Rights Reserved.
  5. *
  6. * This file contains Original Code and/or Modifications of Original Code
  7. * as defined in and that are subject to the Apple Public Source License
  8. * Version 2.0 (the 'License'). You may not use this file except in
  9. * compliance with the License. Please obtain a copy of the License at
  10. * http://www.opensource.apple.com/apsl/ and read it before using this
  11. * file.
  12. *
  13. * The Original Code and all software distributed under the License are
  14. * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  15. * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  16. * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  18. * Please see the License for the specific language governing rights and
  19. * limitations under the License.
  20. *
  21. * @APPLE_LICENSE_HEADER_END@
  22. */
  23. /********************************************************************
  24. *
  25. * objc-msg-arm.s - ARM code to support objc messaging
  26. *
  27. ********************************************************************/
  28. #ifdef __arm__
  29. #include <arm/arch.h>
  30. #include "objc-config.h"
  31. #include "isa.h"
  32. #ifndef _ARM_ARCH_7
  33. # error requires armv7
  34. #endif
  35. // Set FP=1 on architectures that pass parameters in floating-point registers
  36. #if __ARM_ARCH_7K__
  37. # define FP 1
  38. #else
  39. # define FP 0
  40. #endif
  41. #if FP
  42. # if !__ARM_NEON__
  43. # error sorry
  44. # endif
  45. # define FP_RETURN_ZERO \
  46. vmov.i32 q0, #0 ; \
  47. vmov.i32 q1, #0 ; \
  48. vmov.i32 q2, #0 ; \
  49. vmov.i32 q3, #0
  50. # define FP_SAVE \
  51. vpush {q0-q3}
  52. # define FP_RESTORE \
  53. vpop {q0-q3}
  54. #else
  55. # define FP_RETURN_ZERO
  56. # define FP_SAVE
  57. # define FP_RESTORE
  58. #endif
  59. .syntax unified
  60. #define MI_EXTERN(var) \
  61. .non_lazy_symbol_pointer ;\
  62. L##var##$$non_lazy_ptr: ;\
  63. .indirect_symbol var ;\
  64. .long 0
  65. #define MI_GET_EXTERN(reg,var) \
  66. movw reg, :lower16:(L##var##$$non_lazy_ptr-7f-4) ;\
  67. movt reg, :upper16:(L##var##$$non_lazy_ptr-7f-4) ;\
  68. 7: add reg, pc ;\
  69. ldr reg, [reg]
  70. #define MI_GET_ADDRESS(reg,var) \
  71. movw reg, :lower16:(var-7f-4) ;\
  72. movt reg, :upper16:(var-7f-4) ;\
  73. 7: add reg, pc ;\
  74. .data
  75. #if SUPPORT_INDEXED_ISA
  76. .align 2
  77. .globl _objc_indexed_classes
  78. _objc_indexed_classes:
  79. .fill ISA_INDEX_COUNT, 4, 0
  80. #endif
  81. // _objc_restartableRanges is used by method dispatch
  82. // caching code to figure out whether any threads are actively
  83. // in the cache for dispatching. The labels surround the asm code
  84. // that do cache lookups. The tables are zero-terminated.
  85. .macro RestartableEntry
  86. .long LLookupStart$0
  87. .long 0
  88. .short LLookupEnd$0 - LLookupStart$0
  89. .short 0xffff // poor ol' armv7 doesn't support kernel based recovery
  90. .long 0
  91. .endmacro
  92. .align 4
  93. .private_extern _objc_restartableRanges
  94. _objc_restartableRanges:
  95. RestartableEntry _cache_getImp
  96. RestartableEntry _objc_msgSend
  97. RestartableEntry _objc_msgSend_stret
  98. RestartableEntry _objc_msgSendSuper
  99. RestartableEntry _objc_msgSendSuper_stret
  100. RestartableEntry _objc_msgSendSuper2
  101. RestartableEntry _objc_msgSendSuper2_stret
  102. RestartableEntry _objc_msgLookup
  103. RestartableEntry _objc_msgLookup_stret
  104. RestartableEntry _objc_msgLookupSuper2
  105. RestartableEntry _objc_msgLookupSuper2_stret
  106. .fill 16, 1, 0
  107. /********************************************************************
  108. * Names for relative labels
  109. * DO NOT USE THESE LABELS ELSEWHERE
  110. * Reserved labels: 6: 7: 8: 9:
  111. ********************************************************************/
  112. // 6: used by CacheLookup
  113. // 7: used by MI_GET_ADDRESS etc
  114. // 8: used by CacheLookup
  115. #define LNilReceiver 9
  116. #define LNilReceiver_f 9f
  117. #define LNilReceiver_b 9b
  118. /********************************************************************
  119. * Macro parameters
  120. ********************************************************************/
  121. #define NORMAL 0
  122. #define STRET 1
  123. /********************************************************************
  124. *
  125. * Structure definitions.
  126. *
  127. ********************************************************************/
  128. /* objc_super parameter to sendSuper */
  129. #define RECEIVER 0
  130. #define CLASS 4
  131. /* Selected field offsets in class structure */
  132. #define ISA 0
  133. #define SUPERCLASS 4
  134. #define CACHE 8
  135. #define CACHE_MASK 12
  136. /* Field offsets in method cache bucket */
  137. #define CACHED_SEL 0
  138. #define CACHED_IMP 4
  139. /* Selected field offsets in method structure */
  140. #define METHOD_NAME 0
  141. #define METHOD_TYPES 4
  142. #define METHOD_IMP 8
  143. //////////////////////////////////////////////////////////////////////
  144. //
  145. // ENTRY functionName
  146. //
  147. // Assembly directives to begin an exported function.
  148. //
  149. // Takes: functionName - name of the exported function
  150. //////////////////////////////////////////////////////////////////////
  151. .macro ENTRY /* name */
  152. .text
  153. .thumb
  154. .align 5
  155. .globl $0
  156. .thumb_func
  157. $0:
  158. .endmacro
  159. .macro STATIC_ENTRY /*name*/
  160. .text
  161. .thumb
  162. .align 5
  163. .private_extern $0
  164. .thumb_func
  165. $0:
  166. .endmacro
  167. //////////////////////////////////////////////////////////////////////
  168. //
  169. // END_ENTRY functionName
  170. //
  171. // Assembly directives to end an exported function. Just a placeholder,
  172. // a close-parenthesis for ENTRY, until it is needed for something.
  173. //
  174. // Takes: functionName - name of the exported function
  175. //////////////////////////////////////////////////////////////////////
  176. .macro END_ENTRY /* name */
  177. LExit$0:
  178. .endmacro
  179. /////////////////////////////////////////////////////////////////////
  180. //
  181. // CacheLookup NORMAL|STRET <function>
  182. // CacheLookup2 NORMAL|STRET <function>
  183. //
  184. // Locate the implementation for a selector in a class's method cache.
  185. //
  186. // Takes:
  187. // $0 = NORMAL, STRET
  188. // r0 or r1 (STRET) = receiver
  189. // r1 or r2 (STRET) = selector
  190. // r9 = class to search in
  191. //
  192. // On exit: r9 clobbered
  193. // (found) continues after CacheLookup, IMP in r12, eq set
  194. // (not found) continues after CacheLookup2
  195. //
  196. /////////////////////////////////////////////////////////////////////
  197. .macro CacheLookup
  198. //
  199. // Restart protocol:
  200. //
  201. // As soon as we're past the LLookupStart$1 label we may have loaded
  202. // an invalid cache pointer or mask.
  203. //
  204. // When task_restartable_ranges_synchronize() is called,
  205. // (or when a signal hits us) before we're past LLookupEnd$1,
  206. // then our PC will be reset to LCacheMiss$1 which forcefully
  207. // jumps to the cache-miss codepath.
  208. //
  209. // It is assumed that the CacheMiss codepath starts right at the end
  210. // of CacheLookup2 and will re-setup the registers to meet the cache-miss
  211. // requirements:
  212. //
  213. // GETIMP:
  214. // The cache-miss is just returning NULL (setting r9 to 0)
  215. //
  216. // NORMAL and STRET:
  217. // - r0 or r1 (STRET) contains the receiver
  218. // - r1 or r2 (STRET) contains the selector
  219. // - r9 contains the isa (reloaded from r0/r1)
  220. // - other registers are set as per calling conventions
  221. //
  222. LLookupStart$1:
  223. ldrh r12, [r9, #CACHE_MASK] // r12 = mask
  224. ldr r9, [r9, #CACHE] // r9 = buckets
  225. .if $0 == STRET
  226. and r12, r12, r2 // r12 = index = SEL & mask
  227. .else
  228. and r12, r12, r1 // r12 = index = SEL & mask
  229. .endif
  230. add r9, r9, r12, LSL #3 // r9 = bucket = buckets+index*8
  231. ldr r12, [r9, #CACHED_SEL] // r12 = bucket->sel
  232. 6:
  233. .if $0 == STRET
  234. teq r12, r2
  235. .else
  236. teq r12, r1
  237. .endif
  238. bne 8f
  239. ldr r12, [r9, #CACHED_IMP] // r12 = bucket->imp
  240. .if $0 == STRET
  241. tst r12, r12 // set ne for stret forwarding
  242. .else
  243. // eq already set for nonstret forwarding by `teq` above
  244. .endif
  245. .endmacro
  246. .macro CacheLookup2
  247. #if CACHED_SEL != 0
  248. # error this code requires that SEL be at offset 0
  249. #endif
  250. 8:
  251. cmp r12, #1
  252. blo LCacheMiss$1 // if (bucket->sel == 0) cache miss
  253. it eq // if (bucket->sel == 1) cache wrap
  254. ldreq r9, [r9, #CACHED_IMP] // bucket->imp is before first bucket
  255. ldr r12, [r9, #8]! // r12 = (++bucket)->sel
  256. b 6b
  257. LLookupEnd$1:
  258. LCacheMiss$1:
  259. .endmacro
  260. /////////////////////////////////////////////////////////////////////
  261. //
  262. // GetClassFromIsa return-type
  263. //
  264. // Given an Isa, return the class for the Isa.
  265. //
  266. // Takes:
  267. // r9 = class
  268. //
  269. // On exit: r12 clobbered
  270. // r9 contains the class for this Isa.
  271. //
  272. /////////////////////////////////////////////////////////////////////
  273. .macro GetClassFromIsa
  274. #if SUPPORT_INDEXED_ISA
  275. // Note: We are doing a little wasted work here to load values we might not
  276. // need. Branching turns out to be even worse when performance was measured.
  277. MI_GET_ADDRESS(r12, _objc_indexed_classes)
  278. tst.w r9, #ISA_INDEX_IS_NPI_MASK
  279. itt ne
  280. ubfxne r9, r9, #ISA_INDEX_SHIFT, #ISA_INDEX_BITS
  281. ldrne.w r9, [r12, r9, lsl #2]
  282. #endif
  283. .endmacro
  284. /********************************************************************
  285. * IMP cache_getImp(Class cls, SEL sel)
  286. *
  287. * On entry: r0 = class whose cache is to be searched
  288. * r1 = selector to search for
  289. *
  290. * If found, returns method implementation.
  291. * If not found, returns NULL.
  292. ********************************************************************/
  293. STATIC_ENTRY _cache_getImp
  294. mov r9, r0
  295. CacheLookup NORMAL, _cache_getImp
  296. // cache hit, IMP in r12
  297. mov r0, r12
  298. bx lr // return imp
  299. CacheLookup2 GETIMP, _cache_getImp
  300. // cache miss, return nil
  301. mov r0, #0
  302. bx lr
  303. END_ENTRY _cache_getImp
  304. /********************************************************************
  305. *
  306. * id objc_msgSend(id self, SEL _cmd, ...);
  307. * IMP objc_msgLookup(id self, SEL _cmd, ...);
  308. *
  309. * objc_msgLookup ABI:
  310. * IMP returned in r12
  311. * Forwarding returned in Z flag
  312. * r9 reserved for our use but not used
  313. *
  314. ********************************************************************/
  315. ENTRY _objc_msgSend
  316. cbz r0, LNilReceiver_f
  317. ldr r9, [r0] // r9 = self->isa
  318. GetClassFromIsa // r9 = class
  319. CacheLookup NORMAL, _objc_msgSend
  320. // cache hit, IMP in r12, eq already set for nonstret forwarding
  321. bx r12 // call imp
  322. CacheLookup2 NORMAL, _objc_msgSend
  323. // cache miss
  324. ldr r9, [r0] // r9 = self->isa
  325. GetClassFromIsa // r9 = class
  326. b __objc_msgSend_uncached
  327. LNilReceiver:
  328. // r0 is already zero
  329. mov r1, #0
  330. mov r2, #0
  331. mov r3, #0
  332. FP_RETURN_ZERO
  333. bx lr
  334. END_ENTRY _objc_msgSend
  335. ENTRY _objc_msgLookup
  336. cbz r0, LNilReceiver_f
  337. ldr r9, [r0] // r9 = self->isa
  338. GetClassFromIsa // r9 = class
  339. CacheLookup NORMAL, _objc_msgLookup
  340. // cache hit, IMP in r12, eq already set for nonstret forwarding
  341. bx lr
  342. CacheLookup2 NORMAL, _objc_msgLookup
  343. // cache miss
  344. ldr r9, [r0] // r9 = self->isa
  345. GetClassFromIsa // r9 = class
  346. b __objc_msgLookup_uncached
  347. LNilReceiver:
  348. MI_GET_ADDRESS(r12, __objc_msgNil)
  349. bx lr
  350. END_ENTRY _objc_msgLookup
  351. STATIC_ENTRY __objc_msgNil
  352. // r0 is already zero
  353. mov r1, #0
  354. mov r2, #0
  355. mov r3, #0
  356. FP_RETURN_ZERO
  357. bx lr
  358. END_ENTRY __objc_msgNil
  359. /********************************************************************
  360. * void objc_msgSend_stret(void *st_addr, id self, SEL op, ...);
  361. * IMP objc_msgLookup_stret(void *st_addr, id self, SEL op, ...);
  362. *
  363. * objc_msgSend_stret is the struct-return form of msgSend.
  364. * The ABI calls for r0 to be used as the address of the structure
  365. * being returned, with the parameters in the succeeding registers.
  366. *
  367. * On entry: r0 is the address where the structure is returned,
  368. * r1 is the message receiver,
  369. * r2 is the selector
  370. ********************************************************************/
  371. ENTRY _objc_msgSend_stret
  372. cbz r1, LNilReceiver_f
  373. ldr r9, [r1] // r9 = self->isa
  374. GetClassFromIsa // r9 = class
  375. CacheLookup STRET, _objc_msgSend_stret
  376. // cache hit, IMP in r12, ne already set for stret forwarding
  377. bx r12
  378. CacheLookup2 STRET, _objc_msgSend_stret
  379. // cache miss
  380. ldr r9, [r1] // r9 = self->isa
  381. GetClassFromIsa // r9 = class
  382. b __objc_msgSend_stret_uncached
  383. LNilReceiver:
  384. bx lr
  385. END_ENTRY _objc_msgSend_stret
  386. ENTRY _objc_msgLookup_stret
  387. cbz r1, LNilReceiver_f
  388. ldr r9, [r1] // r9 = self->isa
  389. GetClassFromIsa // r9 = class
  390. CacheLookup STRET, _objc_msgLookup_stret
  391. // cache hit, IMP in r12, ne already set for stret forwarding
  392. bx lr
  393. CacheLookup2 STRET, _objc_msgLookup_stret
  394. // cache miss
  395. ldr r9, [r1] // r9 = self->isa
  396. GetClassFromIsa // r9 = class
  397. b __objc_msgLookup_stret_uncached
  398. LNilReceiver:
  399. MI_GET_ADDRESS(r12, __objc_msgNil_stret)
  400. bx lr
  401. END_ENTRY _objc_msgLookup_stret
  402. STATIC_ENTRY __objc_msgNil_stret
  403. bx lr
  404. END_ENTRY __objc_msgNil_stret
  405. /********************************************************************
  406. * id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
  407. *
  408. * struct objc_super {
  409. * id receiver;
  410. * Class cls; // the class to search
  411. * }
  412. ********************************************************************/
  413. ENTRY _objc_msgSendSuper
  414. ldr r9, [r0, #CLASS] // r9 = struct super->class
  415. CacheLookup NORMAL, _objc_msgSendSuper
  416. // cache hit, IMP in r12, eq already set for nonstret forwarding
  417. ldr r0, [r0, #RECEIVER] // load real receiver
  418. bx r12 // call imp
  419. CacheLookup2 NORMAL, _objc_msgSendSuper
  420. // cache miss
  421. ldr r9, [r0, #CLASS] // r9 = struct super->class
  422. ldr r0, [r0, #RECEIVER] // load real receiver
  423. b __objc_msgSend_uncached
  424. END_ENTRY _objc_msgSendSuper
  425. /********************************************************************
  426. * id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
  427. *
  428. * struct objc_super {
  429. * id receiver;
  430. * Class cls; // SUBCLASS of the class to search
  431. * }
  432. ********************************************************************/
  433. ENTRY _objc_msgSendSuper2
  434. ldr r9, [r0, #CLASS] // class = struct super->class
  435. ldr r9, [r9, #SUPERCLASS] // class = class->superclass
  436. CacheLookup NORMAL, _objc_msgSendSuper2
  437. // cache hit, IMP in r12, eq already set for nonstret forwarding
  438. ldr r0, [r0, #RECEIVER] // load real receiver
  439. bx r12 // call imp
  440. CacheLookup2 NORMAL, _objc_msgSendSuper2
  441. // cache miss
  442. ldr r9, [r0, #CLASS] // class = struct super->class
  443. ldr r9, [r9, #SUPERCLASS] // class = class->superclass
  444. ldr r0, [r0, #RECEIVER] // load real receiver
  445. b __objc_msgSend_uncached
  446. END_ENTRY _objc_msgSendSuper2
  447. ENTRY _objc_msgLookupSuper2
  448. ldr r9, [r0, #CLASS] // class = struct super->class
  449. ldr r9, [r9, #SUPERCLASS] // class = class->superclass
  450. CacheLookup NORMAL, _objc_msgLookupSuper2
  451. // cache hit, IMP in r12, eq already set for nonstret forwarding
  452. ldr r0, [r0, #RECEIVER] // load real receiver
  453. bx lr
  454. CacheLookup2 NORMAL, _objc_msgLookupSuper2
  455. // cache miss
  456. ldr r9, [r0, #CLASS]
  457. ldr r9, [r9, #SUPERCLASS] // r9 = class to search
  458. ldr r0, [r0, #RECEIVER] // load real receiver
  459. b __objc_msgLookup_uncached
  460. END_ENTRY _objc_msgLookupSuper2
  461. /********************************************************************
  462. * void objc_msgSendSuper_stret(void *st_addr, objc_super *self, SEL op, ...);
  463. *
  464. * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
  465. * The ABI calls for r0 to be used as the address of the structure
  466. * being returned, with the parameters in the succeeding registers.
  467. *
  468. * On entry: r0 is the address where the structure is returned,
  469. * r1 is the address of the objc_super structure,
  470. * r2 is the selector
  471. ********************************************************************/
  472. ENTRY _objc_msgSendSuper_stret
  473. ldr r9, [r1, #CLASS] // r9 = struct super->class
  474. CacheLookup STRET, _objc_msgSendSuper_stret
  475. // cache hit, IMP in r12, ne already set for stret forwarding
  476. ldr r1, [r1, #RECEIVER] // load real receiver
  477. bx r12 // call imp
  478. CacheLookup2 STRET, _objc_msgSendSuper_stret
  479. // cache miss
  480. ldr r9, [r1, #CLASS] // r9 = struct super->class
  481. ldr r1, [r1, #RECEIVER] // load real receiver
  482. b __objc_msgSend_stret_uncached
  483. END_ENTRY _objc_msgSendSuper_stret
  484. /********************************************************************
  485. * id objc_msgSendSuper2_stret
  486. ********************************************************************/
  487. ENTRY _objc_msgSendSuper2_stret
  488. ldr r9, [r1, #CLASS] // class = struct super->class
  489. ldr r9, [r9, #SUPERCLASS] // class = class->superclass
  490. CacheLookup STRET, _objc_msgSendSuper2_stret
  491. // cache hit, IMP in r12, ne already set for stret forwarding
  492. ldr r1, [r1, #RECEIVER] // load real receiver
  493. bx r12 // call imp
  494. CacheLookup2 STRET, _objc_msgSendSuper2_stret
  495. // cache miss
  496. ldr r9, [r1, #CLASS] // class = struct super->class
  497. ldr r9, [r9, #SUPERCLASS] // class = class->superclass
  498. ldr r1, [r1, #RECEIVER] // load real receiver
  499. b __objc_msgSend_stret_uncached
  500. END_ENTRY _objc_msgSendSuper2_stret
  501. ENTRY _objc_msgLookupSuper2_stret
  502. ldr r9, [r1, #CLASS] // class = struct super->class
  503. ldr r9, [r9, #SUPERCLASS] // class = class->superclass
  504. CacheLookup STRET, _objc_msgLookupSuper2_stret
  505. // cache hit, IMP in r12, ne already set for stret forwarding
  506. ldr r1, [r1, #RECEIVER] // load real receiver
  507. bx lr
  508. CacheLookup2 STRET, _objc_msgLookupSuper2_stret
  509. // cache miss
  510. ldr r9, [r1, #CLASS]
  511. ldr r9, [r9, #SUPERCLASS] // r9 = class to search
  512. ldr r1, [r1, #RECEIVER] // load real receiver
  513. b __objc_msgLookup_stret_uncached
  514. END_ENTRY _objc_msgLookupSuper2_stret
  515. /////////////////////////////////////////////////////////////////////
  516. //
  517. // MethodTableLookup NORMAL|STRET
  518. //
  519. // Locate the implementation for a selector in a class's method lists.
  520. //
  521. // Takes:
  522. // $0 = NORMAL, STRET
  523. // r0 or r1 (STRET) = receiver
  524. // r1 or r2 (STRET) = selector
  525. // r9 = class to search in
  526. //
  527. // On exit: IMP in r12, eq/ne set for forwarding
  528. //
  529. /////////////////////////////////////////////////////////////////////
  530. .macro MethodTableLookup
  531. stmfd sp!, {r0-r3,r7,lr}
  532. add r7, sp, #16
  533. sub sp, #8 // align stack
  534. FP_SAVE
  535. // lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
  536. .if $0 == NORMAL
  537. // receiver already in r0
  538. // selector already in r1
  539. .else
  540. mov r0, r1 // receiver
  541. mov r1, r2 // selector
  542. .endif
  543. mov r2, r9 // class to search
  544. mov r3, #3 // LOOKUP_INITIALIZE | LOOKUP_INITIALIZE
  545. blx _lookUpImpOrForward
  546. mov r12, r0 // r12 = IMP
  547. .if $0 == NORMAL
  548. cmp r12, r12 // set eq for nonstret forwarding
  549. .else
  550. tst r12, r12 // set ne for stret forwarding
  551. .endif
  552. FP_RESTORE
  553. add sp, #8 // align stack
  554. ldmfd sp!, {r0-r3,r7,lr}
  555. .endmacro
  556. /********************************************************************
  557. *
  558. * _objc_msgSend_uncached
  559. * _objc_msgSend_stret_uncached
  560. * _objc_msgLookup_uncached
  561. * _objc_msgLookup_stret_uncached
  562. * The uncached method lookup.
  563. *
  564. ********************************************************************/
  565. STATIC_ENTRY __objc_msgSend_uncached
  566. // THIS IS NOT A CALLABLE C FUNCTION
  567. // Out-of-band r9 is the class to search
  568. MethodTableLookup NORMAL // returns IMP in r12
  569. bx r12
  570. END_ENTRY __objc_msgSend_uncached
  571. STATIC_ENTRY __objc_msgSend_stret_uncached
  572. // THIS IS NOT A CALLABLE C FUNCTION
  573. // Out-of-band r9 is the class to search
  574. MethodTableLookup STRET // returns IMP in r12
  575. bx r12
  576. END_ENTRY __objc_msgSend_stret_uncached
  577. STATIC_ENTRY __objc_msgLookup_uncached
  578. // THIS IS NOT A CALLABLE C FUNCTION
  579. // Out-of-band r9 is the class to search
  580. MethodTableLookup NORMAL // returns IMP in r12
  581. bx lr
  582. END_ENTRY __objc_msgLookup_uncached
  583. STATIC_ENTRY __objc_msgLookup_stret_uncached
  584. // THIS IS NOT A CALLABLE C FUNCTION
  585. // Out-of-band r9 is the class to search
  586. MethodTableLookup STRET // returns IMP in r12
  587. bx lr
  588. END_ENTRY __objc_msgLookup_stret_uncached
  589. /********************************************************************
  590. *
  591. * id _objc_msgForward(id self, SEL _cmd,...);
  592. *
  593. * _objc_msgForward and _objc_msgForward_stret are the externally-callable
  594. * functions returned by things like method_getImplementation().
  595. * _objc_msgForward_impcache is the function pointer actually stored in
  596. * method caches.
  597. *
  598. ********************************************************************/
  599. MI_EXTERN(__objc_forward_handler)
  600. MI_EXTERN(__objc_forward_stret_handler)
  601. STATIC_ENTRY __objc_msgForward_impcache
  602. // Method cache version
  603. // THIS IS NOT A CALLABLE C FUNCTION
  604. // Out-of-band Z is 0 (EQ) for normal, 1 (NE) for stret
  605. beq __objc_msgForward
  606. b __objc_msgForward_stret
  607. END_ENTRY __objc_msgForward_impcache
  608. ENTRY __objc_msgForward
  609. // Non-stret version
  610. MI_GET_EXTERN(r12, __objc_forward_handler)
  611. ldr r12, [r12]
  612. bx r12
  613. END_ENTRY __objc_msgForward
  614. ENTRY __objc_msgForward_stret
  615. // Struct-return version
  616. MI_GET_EXTERN(r12, __objc_forward_stret_handler)
  617. ldr r12, [r12]
  618. bx r12
  619. END_ENTRY __objc_msgForward_stret
  620. ENTRY _objc_msgSend_noarg
  621. b _objc_msgSend
  622. END_ENTRY _objc_msgSend_noarg
  623. ENTRY _objc_msgSend_debug
  624. b _objc_msgSend
  625. END_ENTRY _objc_msgSend_debug
  626. ENTRY _objc_msgSendSuper2_debug
  627. b _objc_msgSendSuper2
  628. END_ENTRY _objc_msgSendSuper2_debug
  629. ENTRY _objc_msgSend_stret_debug
  630. b _objc_msgSend_stret
  631. END_ENTRY _objc_msgSend_stret_debug
  632. ENTRY _objc_msgSendSuper2_stret_debug
  633. b _objc_msgSendSuper2_stret
  634. END_ENTRY _objc_msgSendSuper2_stret_debug
  635. ENTRY _method_invoke
  636. // r1 is method triplet instead of SEL
  637. ldr r12, [r1, #METHOD_IMP]
  638. ldr r1, [r1, #METHOD_NAME]
  639. bx r12
  640. END_ENTRY _method_invoke
  641. ENTRY _method_invoke_stret
  642. // r2 is method triplet instead of SEL
  643. ldr r12, [r2, #METHOD_IMP]
  644. ldr r2, [r2, #METHOD_NAME]
  645. bx r12
  646. END_ENTRY _method_invoke_stret
  647. .section __DATA,__objc_msg_break
  648. .long 0
  649. .long 0
  650. #endif