foreign export dynamic for MacOS X
Sigbjorn Finne
sof@galois.com
Wed, 17 Apr 2002 08:32:17 -0700
Good stuff, change committed.
thanks,
--sigbjorn
----- Original Message -----
From: "Wolfgang Thaller" <wolfgang.thaller@gmx.net>
To: <hugs-bugs@haskell.org>
Sent: Wednesday, April 17, 2002 03:02
Subject: foreign export dynamic for MacOS X
> I recently added PowerPC thunk creation to GHC, and I thought it
> would also be useful for hugs.
>
> Cheers,
>
> Wolfgang Thaller
>
> --- for src/builtin.c:
>
> struct thunk_data {
> struct thunk_data* next;
> struct thunk_data* prev;
> HugsStablePtr stable;
> #if defined(__ppc__)
> char code[13*4];
> #else
> char code[16];
> #endif
> };
>
> struct thunk_data* foreignThunks = 0;
>
> static void* mkThunk(void* app, HugsStablePtr s) {
> struct thunk_data* thunk
> = (struct thunk_data*)malloc(sizeof(struct thunk_data));
> char* pc;
> if (!thunk) {
> /* ToDo: better cleanup */
> printf("Can't allocate thunk for foreign export dynamic\n");
> exit(1);
> }
> if (foreignThunks) { /* non-empty list */
> foreignThunks->prev = thunk;
> }
> thunk->next = foreignThunks;
> thunk->prev = 0;
> foreignThunks = thunk;
> thunk->stable = s;
> pc = &thunk->code[0];
> #if defined(__i386__)
> /* 3 bytes: pushl (%esp) */
> *pc++ = 0xff; *pc++ = 0x34; *pc++ = 0x24;
>
> /* 8 bytes: movl s,4(%esp) */
> *pc++ = 0xc7; *pc++ = 0x44; *pc++ = 0x24; *pc++ = 0x04;
> *((HugsStablePtr*)pc)++ = s;
>
> /* 5 bytes: jmp app */
> *pc++ = 0xe9;
> *((int*)pc)++ = (char*)app - ((char*)&(thunk->code[16]));
> #elif defined(__ppc__) && defined(__GNUC__)
> /* This is only for MacOS X.
> * It does not work on MacOS 9 because of the very strange
> * handling of function pointers in OS 9.
> * I don't know about LinuxPPC calling conventions.
> * Please note that it only works for up to 7 arguments.
> */
>
> {
> unsigned long *adj_code = (unsigned long*)pc;
> // make room for extra arguments
> adj_code[0] = 0x7d2a4b78; //mr r10,r9
> adj_code[1] = 0x7d094378; //mr r9,r8
> adj_code[2] = 0x7ce83b78; //mr r8,r7
> adj_code[3] = 0x7cc73378; //mr r7,r6
> adj_code[4] = 0x7ca62b78; //mr r6,r5
> adj_code[5] = 0x7c852378; //mr r5,r4
> adj_code[6] = 0x7c641b78; //mr r4,r3
>
> adj_code[7] = 0x3c000000; //lis r0,hi(app)
> adj_code[7] |= ((unsigned long)app) >> 16;
>
> adj_code[8] = 0x3c600000; //lis r3,hi(s)
> adj_code[8] |= ((unsigned long)s) >> 16;
>
> adj_code[9] = 0x60000000; //ori r0,r0,lo(app)
> adj_code[9] |= ((unsigned long)app) & 0xFFFF;
>
> adj_code[10] = 0x60630000; //ori r3,r3,lo(s)
> adj_code[10] |= ((unsigned long)s) & 0xFFFF;
>
> adj_code[11] = 0x7c0903a6; //mtctr r0
> adj_code[12] = 0x4e800420; //bctr
>
> pc = (char*) &adj_code[13];
>
> // Flush the Instruction cache:
> //MakeDataExecutable(adjustor,4*13);
> /* This would require us to link with CoreServices.framework
*/
> { /* this should do the same: */
> int n = 13;
> unsigned long *p = adj_code;
> while(n--)
> {
> __asm__ volatile ("dcbf 0,%0\n\tsync\n\ticbi 0,%0"
> : : "g" (p));
> p++;
> }
> __asm__ volatile ("sync\n\tisync");
> }
> }
> #else
> ERRMSG(0) "Foreign export dynamic is not supported on this
architecture"
> EEND;
> #endif
> assert(pc <= &thunk->code[0] + sizeof(thunk->code));
> return &thunk->code; /* a pointer into the middle of the thunk */
> }
> _______________________________________________
> Hugs-Bugs mailing list
> Hugs-Bugs@haskell.org
> http://www.haskell.org/mailman/listinfo/hugs-bugs