ARM stuff.

main
theraven 14 years ago
parent dc8be2905e
commit 4c9acdf153

@ -3,6 +3,7 @@
#include <objc/runtime.h>
#include <assert.h>
#include <string.h>
#include <class.h>
id objc_msgSend(id, SEL, ...);
@ -38,6 +39,7 @@ int main(void)
TestCls = objc_getClass("Test");
objc_msgSend(TestCls, @selector(nothing));
objc_msgSend(TestCls, @selector(missing));
assert(0 == objc_msgSend(0, @selector(nothing)));
id a = objc_msgSend(objc_getClass("Test"), @selector(foo));
assert((id)0x42 == a);
a = objc_msgSend(TestCls, @selector(foo));

@ -274,7 +274,7 @@ static inline Class classForObject(id obj)
{
if (sizeof(Class) == 4)
{
return SmallObjectClasses[1];
return SmallObjectClasses[0];
}
else
{

@ -431,6 +431,15 @@ BOOL objc_registerSmallObjectClass_np(Class class, uintptr_t mask)
{
return NO;
}
if (sizeof(void*) == 4)
{
if (Nil == SmallObjectClasses[0])
{
SmallObjectClasses[0] = class;
return YES;
}
return NO;
}
if (Nil != SmallObjectClasses[mask])
{
return NO;

@ -2,7 +2,8 @@
#include "objc_msgSend.x86-64.S"
#elif __i386
#include "objc_msgSend.x86-32.S"
#elif __arm__
#include "objc_msgSend.arm.S"
#else
//#elif __arm__
#warning objc_msgSend() not implemented for your architecture
#endif

@ -0,0 +1,98 @@
#define DTABLE_OFFSET 32
#define SMALLOBJ_MASK 1
#define SHIFT_OFFSET 4
#define DATA_OFFSET 12
#define SLOT_OFFSET 16
.syntax unified
// Macro for testing: logs a register value to standard error
.macro LOG reg
push {r0-r3, ip,lr}
mov r0, \reg
bl logInt(PLT)
pop {r0-r3, ip,lr}
.endm
.macro MSGSEND receiver, sel
teq \receiver, 0
beq 4f // Skip everything if the receiver is nil
push {r4-r6} // We're going to use these three as
// scratch registers, so save them now
tst \receiver, SMALLOBJ_MASK // Sets Z if this is not a small int
ldrne r4, LSmallIntClass // Small Int class -> r4 if this is a small int
ldrne r4, [r4]
ldreq r4, [\receiver] // Load class to r4 if not a small int
ldr r4, [r4, #DTABLE_OFFSET] // Dtable -> r4
ldr r5, LUninstalledDtable // &uninstalled_dtable -> r5
ldr r5, [r5]
teq r4, r5 // If dtable == &uninstalled_dtable
beq 5f // Do a slow lookup
ldr r5, [\sel] // selector->index -> r5
ldr r6, [r4, #SHIFT_OFFSET] // dtable->shift -> r6
ldr r4, [r4, #DATA_OFFSET] // dtable->data -> r4
teq r6, #8 // If this is a small dtable, jump to the small dtable handlers
beq 1f
teq r6, #0
beq 2f
and r6, r5, #0xff0000
ldr r4, [r4, r6, asr#14]
1: // dtable16
and r6, r5, #0xff00
ldr r4, [r4, r6, asr#6]
2: // dtable8
and r6, r5, #0xff
ldr ip, [r4, r6, asl#2]
teq ip, #0 // If the slot is nil
beq 5f // Go to the slow path and do the forwarding stuff
ldr ip, [ip, #SLOT_OFFSET] // Load the method from the slot
3:
pop {r4-r6} // Restore the saved callee-save registers
mov pc, ip
4: // Nil receiver
mov r0, 0
mov r1, 0
mov pc, lr
5: // Slow lookup
push {r0-r3, lr} // Save anything that will be clobbered by the call
push {\receiver} // &self, _cmd in arguments
mov r0, sp
mov r1, \sel
bl slowMsgLookup(PLT)
mov ip, r0 // IMP -> ip
pop {r5} // restore (modified) self to r5
pop {r0-r3, lr} // Load clobbered registers
mov \receiver, r5
b 3b
.endm
.globl objc_msgSend
.type objc_msgSend, %function
objc_msgSend:
MSGSEND r0, r1
.globl objc_msgSend_sret
.type objc_msgSend_sret, %function
objc_msgSend_sret:
MSGSEND r1, r2
LSmallIntClass:
.long SmallObjectClasses
.align 2
LUninstalledDtable:
.long uninstalled_dtable
.align 2

@ -75,7 +75,6 @@
call __i686.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
mov SmallObjectClasses@GOT(%ebx), %eax
addl $4, %eax
mov (%eax), %eax
popl %ebx
jmp 1b

@ -110,9 +110,9 @@ IMP slowMsgLookup(id *receiver, SEL cmd)
return objc_msg_lookup_sender(receiver, cmd, nil)->method;
}
PRIVATE void logInt(long long a)
PRIVATE void logInt(void *a)
{
fprintf(stderr, "Value: %llx\n", a);
fprintf(stderr, "Value: %p\n", a);
}
Slot_t (*objc_plane_lookup)(id *receiver, SEL op, id sender) =

Loading…
Cancel
Save