More Darwin.
This commit is contained in:
parent
a995e477ff
commit
a46395ecf9
10 changed files with 311 additions and 246 deletions
26
src/lib9/ffork-Darwin.c
Normal file
26
src/lib9/ffork-Darwin.c
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include <lib9.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
extern int __isthreaded;
|
||||||
|
int
|
||||||
|
ffork(int flags, void(*fn)(void*), void *arg)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
pthread_t tid;
|
||||||
|
|
||||||
|
if(flags != (RFMEM|RFNOWAIT)){
|
||||||
|
werrstr("ffork unsupported");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pthread_create(&tid, NULL, (void*(*)(void*))fn, arg) < 0)
|
||||||
|
return -1;
|
||||||
|
return (int)tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getfforkid(void)
|
||||||
|
{
|
||||||
|
return (int)pthread_self();
|
||||||
|
}
|
||||||
|
|
||||||
246
src/lib9/lib9.h
246
src/lib9/lib9.h
|
|
@ -1,246 +0,0 @@
|
||||||
/*
|
|
||||||
* Lib9 is miscellany from the Plan 9 C library that doesn't
|
|
||||||
* fit into libutf or into libfmt, but is still missing from traditional
|
|
||||||
* Unix C libraries.
|
|
||||||
*/
|
|
||||||
#ifndef _LIB9H_
|
|
||||||
#define _LIB9H_ 1
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#ifndef _FMTH_
|
|
||||||
# include <fmt.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define nil ((void*)0)
|
|
||||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
|
||||||
|
|
||||||
#define _NEEDUCHAR 1
|
|
||||||
#define _NEEDUSHORT 1
|
|
||||||
#define _NEEDUINT 1
|
|
||||||
#define _NEEDULONG 1
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
# include <sys/types.h>
|
|
||||||
# if defined(__USE_MISC)
|
|
||||||
# undef _NEEDUSHORT
|
|
||||||
# undef _NEEDUINT
|
|
||||||
# undef _NEEDULONG
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#if defined(__FreeBSD__)
|
|
||||||
# include <sys/types.h>
|
|
||||||
# if !defined(_POSIX_SOURCE)
|
|
||||||
# undef _NEEDUSHORT
|
|
||||||
# undef _NEEDUINT
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef signed char schar;
|
|
||||||
typedef unsigned int u32int;
|
|
||||||
#ifdef _NEEDUCHAR
|
|
||||||
typedef unsigned char uchar;
|
|
||||||
#endif
|
|
||||||
#ifdef _NEEDUSHORT
|
|
||||||
typedef unsigned short ushort;
|
|
||||||
#endif
|
|
||||||
#ifdef _NEEDUINT
|
|
||||||
typedef unsigned int uint;
|
|
||||||
#endif
|
|
||||||
#ifdef _NEEDULONG
|
|
||||||
typedef unsigned long ulong;
|
|
||||||
#endif
|
|
||||||
typedef unsigned long long uvlong;
|
|
||||||
typedef long long vlong;
|
|
||||||
|
|
||||||
/* rfork to create new process running fn(arg) */
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
|
||||||
#undef RFFDG
|
|
||||||
#undef RFNOTEG
|
|
||||||
#undef RFPROC
|
|
||||||
#undef RFMEM
|
|
||||||
#undef RFNOWAIT
|
|
||||||
#undef RFCFDG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
/* RFNAMEG = (1<<0), */
|
|
||||||
/* RFENVG = (1<<1), */
|
|
||||||
RFFDG = (1<<2),
|
|
||||||
RFNOTEG = (1<<3),
|
|
||||||
RFPROC = (1<<4),
|
|
||||||
RFMEM = (1<<5),
|
|
||||||
RFNOWAIT = (1<<6),
|
|
||||||
/* RFCNAMEG = (1<<10), */
|
|
||||||
/* RFCENVG = (1<<11), */
|
|
||||||
RFCFDG = (1<<12),
|
|
||||||
/* RFREND = (1<<13), */
|
|
||||||
/* RFNOMNT = (1<<14) */
|
|
||||||
};
|
|
||||||
extern int ffork(int, void(*)(void*), void*);
|
|
||||||
|
|
||||||
/* wait for processes */
|
|
||||||
#define wait _p9wait
|
|
||||||
typedef struct Waitmsg Waitmsg;
|
|
||||||
struct Waitmsg
|
|
||||||
{
|
|
||||||
int pid; /* of loved one */
|
|
||||||
ulong time[3]; /* of loved one & descendants */
|
|
||||||
char *msg;
|
|
||||||
};
|
|
||||||
extern int await(char*, int);
|
|
||||||
extern Waitmsg* wait(void);
|
|
||||||
|
|
||||||
/* synchronization */
|
|
||||||
typedef struct Lock Lock;
|
|
||||||
struct Lock
|
|
||||||
{
|
|
||||||
int val;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int _tas(void*);
|
|
||||||
extern void lock(Lock*);
|
|
||||||
extern void unlock(Lock*);
|
|
||||||
extern int canlock(Lock*);
|
|
||||||
|
|
||||||
typedef struct QLp QLp;
|
|
||||||
struct QLp
|
|
||||||
{
|
|
||||||
int inuse;
|
|
||||||
QLp *next;
|
|
||||||
int state;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct QLock QLock;
|
|
||||||
struct QLock
|
|
||||||
{
|
|
||||||
Lock lock;
|
|
||||||
int locked;
|
|
||||||
QLp *head;
|
|
||||||
QLp *tail;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void qlock(QLock*);
|
|
||||||
extern void qunlock(QLock*);
|
|
||||||
extern int canqlock(QLock*);
|
|
||||||
extern void _qlockinit(ulong (*)(ulong, ulong));
|
|
||||||
|
|
||||||
typedef struct RWLock RWLock;
|
|
||||||
struct RWLock
|
|
||||||
{
|
|
||||||
Lock lock;
|
|
||||||
int readers;
|
|
||||||
int writer;
|
|
||||||
QLp *head;
|
|
||||||
QLp *tail;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void rlock(RWLock*);
|
|
||||||
extern void runlock(RWLock*);
|
|
||||||
extern int canrlock(RWLock*);
|
|
||||||
extern void wlock(RWLock*);
|
|
||||||
extern void wunlock(RWLock*);
|
|
||||||
extern int canwlock(RWLock*);
|
|
||||||
|
|
||||||
typedef struct Rendez Rendez;
|
|
||||||
struct Rendez
|
|
||||||
{
|
|
||||||
QLock *l;
|
|
||||||
QLp *head;
|
|
||||||
QLp *tail;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void rsleep(Rendez*);
|
|
||||||
extern int rwakeup(Rendez*);
|
|
||||||
extern int rwakeupall(Rendez*);
|
|
||||||
|
|
||||||
extern ulong rendezvous(ulong, ulong);
|
|
||||||
|
|
||||||
/* one of a kind */
|
|
||||||
extern void sysfatal(char*, ...);
|
|
||||||
extern int nrand(int);
|
|
||||||
extern void setmalloctag(void*, ulong);
|
|
||||||
extern void setrealloctag(void*, ulong);
|
|
||||||
extern void *mallocz(ulong, int);
|
|
||||||
extern long readn(int, void*, long);
|
|
||||||
extern void exits(char*);
|
|
||||||
extern void _exits(char*);
|
|
||||||
extern ulong getcallerpc(void*);
|
|
||||||
|
|
||||||
/* string routines */
|
|
||||||
extern char* strecpy(char*, char*, char*);
|
|
||||||
extern int tokenize(char*, char**, int);
|
|
||||||
extern int cistrncmp(char*, char*, int);
|
|
||||||
extern int cistrcmp(char*, char*);
|
|
||||||
extern char* cistrstr(char*, char*);
|
|
||||||
extern int getfields(char*, char**, int, int, char*);
|
|
||||||
extern int gettokens(char *, char **, int, char *);
|
|
||||||
|
|
||||||
/* formatting helpers */
|
|
||||||
extern int dec64(uchar*, int, char*, int);
|
|
||||||
extern int enc64(char*, int, uchar*, int);
|
|
||||||
extern int dec32(uchar*, int, char*, int);
|
|
||||||
extern int enc32(char*, int, uchar*, int);
|
|
||||||
extern int dec16(uchar*, int, char*, int);
|
|
||||||
extern int enc16(char*, int, uchar*, int);
|
|
||||||
extern int encodefmt(Fmt*);
|
|
||||||
|
|
||||||
/* error string */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
ERRMAX = 128
|
|
||||||
};
|
|
||||||
extern void rerrstr(char*, uint);
|
|
||||||
extern void werrstr(char*, ...);
|
|
||||||
extern int errstr(char*, uint);
|
|
||||||
|
|
||||||
/* compiler directives on plan 9 */
|
|
||||||
#define USED(x) if(x){}else{}
|
|
||||||
#define SET(x) ((x)=0)
|
|
||||||
|
|
||||||
/* command line */
|
|
||||||
extern char *argv0;
|
|
||||||
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
|
|
||||||
argv[0] && argv[0][0]=='-' && argv[0][1];\
|
|
||||||
argc--, argv++) {\
|
|
||||||
char *_args, *_argt;\
|
|
||||||
Rune _argc;\
|
|
||||||
_args = &argv[0][1];\
|
|
||||||
if(_args[0]=='-' && _args[1]==0){\
|
|
||||||
argc--; argv++; break;\
|
|
||||||
}\
|
|
||||||
_argc = 0;\
|
|
||||||
while(*_args && (_args += chartorune(&_argc, _args)))\
|
|
||||||
switch(_argc)
|
|
||||||
#define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
|
|
||||||
#define ARGF() (_argt=_args, _args="",\
|
|
||||||
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
|
|
||||||
#define EARGF(x) (_argt=_args, _args="",\
|
|
||||||
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
|
|
||||||
|
|
||||||
#define ARGC() _argc
|
|
||||||
|
|
||||||
#define OREAD O_RDONLY
|
|
||||||
#define OWRITE O_WRONLY
|
|
||||||
#define AEXIST 0
|
|
||||||
#define AREAD 4
|
|
||||||
#define AWRITE 2
|
|
||||||
#define AEXEC 1
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _LIB9H_ */
|
|
||||||
2
src/lib9/rendez-Darwin.c
Normal file
2
src/lib9/rendez-Darwin.c
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include "rendez-pthread.c"
|
||||||
|
|
||||||
1
src/lib9/rendez-FreeBSD.c
Normal file
1
src/lib9/rendez-FreeBSD.c
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#include "rendez-signal.c"
|
||||||
1
src/lib9/rendez-Linux.c
Normal file
1
src/lib9/rendez-Linux.c
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#include "rendez-signal.c"
|
||||||
168
src/lib9/rendez-pthread.c
Normal file
168
src/lib9/rendez-pthread.c
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
/*
|
||||||
|
NAME
|
||||||
|
rendezvous - user level process synchronization
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
ulong rendezvous(ulong tag, ulong value)
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
The rendezvous system call allows two processes to synchro-
|
||||||
|
nize and exchange a value. In conjunction with the shared
|
||||||
|
memory system calls (see segattach(2) and fork(2)), it
|
||||||
|
enables parallel programs to control their scheduling.
|
||||||
|
|
||||||
|
Two processes wishing to synchronize call rendezvous with a
|
||||||
|
common tag, typically an address in memory they share. One
|
||||||
|
process will arrive at the rendezvous first; it suspends
|
||||||
|
execution until a second arrives. When a second process
|
||||||
|
meets the rendezvous the value arguments are exchanged
|
||||||
|
between the processes and returned as the result of the
|
||||||
|
respective rendezvous system calls. Both processes are
|
||||||
|
awakened when the rendezvous succeeds.
|
||||||
|
|
||||||
|
The set of tag values which two processes may use to
|
||||||
|
rendezvous-their tag space-is inherited when a process
|
||||||
|
forks, unless RFREND is set in the argument to rfork; see
|
||||||
|
fork(2).
|
||||||
|
|
||||||
|
If a rendezvous is interrupted the return value is ~0, so
|
||||||
|
that value should not be used in normal communication.
|
||||||
|
|
||||||
|
* This assumes we're using pthreads and simulates rendezvous using
|
||||||
|
* shared memory and mutexes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <lib9.h>
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
VOUSHASH = 257,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Vous Vous;
|
||||||
|
struct Vous
|
||||||
|
{
|
||||||
|
Vous *link;
|
||||||
|
Lock lk;
|
||||||
|
ulong val;
|
||||||
|
ulong tag;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
ign(int x)
|
||||||
|
{
|
||||||
|
USED(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void /*__attribute__((constructor))*/
|
||||||
|
ignusr1(void)
|
||||||
|
{
|
||||||
|
signal(SIGUSR1, ign);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vous vouspool[2048];
|
||||||
|
static int nvousused;
|
||||||
|
static Vous *vousfree;
|
||||||
|
static Vous *voushash[VOUSHASH];
|
||||||
|
static Lock vouslock;
|
||||||
|
|
||||||
|
static Vous*
|
||||||
|
getvous(void)
|
||||||
|
{
|
||||||
|
Vous *v;
|
||||||
|
|
||||||
|
if(vousfree){
|
||||||
|
v = vousfree;
|
||||||
|
vousfree = v->link;
|
||||||
|
}else if(nvousused < nelem(vouspool)){
|
||||||
|
v = &vouspool[nvousused++];
|
||||||
|
pthread_mutex_init(&v->mutex, NULL);
|
||||||
|
}else
|
||||||
|
abort();
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
putvous(Vous *v)
|
||||||
|
{
|
||||||
|
lock(&vouslock);
|
||||||
|
v->link = vousfree;
|
||||||
|
vousfree = v;
|
||||||
|
unlock(&vouslock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vous*
|
||||||
|
findvous(ulong tag, ulong val, int *found)
|
||||||
|
{
|
||||||
|
int h;
|
||||||
|
Vous *v, **l;
|
||||||
|
|
||||||
|
lock(&vouslock);
|
||||||
|
h = tag%VOUSHASH;
|
||||||
|
for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
|
||||||
|
if(v->tag == tag){
|
||||||
|
*l = v->link;
|
||||||
|
*found = 1;
|
||||||
|
unlock(&vouslock);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v = getvous();
|
||||||
|
v->link = voushash[h];
|
||||||
|
v->val = val;
|
||||||
|
v->tag = tag;
|
||||||
|
lock(&v->lk);
|
||||||
|
voushash[h] = v;
|
||||||
|
unlock(&vouslock);
|
||||||
|
*found = 0;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DBG 0
|
||||||
|
ulong
|
||||||
|
rendezvous(ulong tag, ulong val)
|
||||||
|
{
|
||||||
|
int found;
|
||||||
|
ulong rval;
|
||||||
|
Vous *v;
|
||||||
|
|
||||||
|
v = findvous(tag, val, &found);
|
||||||
|
if(!found){
|
||||||
|
if(DBG)fprint(2, "tag %lux, sleeping on %p\n", tag, v);
|
||||||
|
/*
|
||||||
|
* No rendezvous partner was found; the next guy
|
||||||
|
* through will find v and wake us, so we must go
|
||||||
|
* to sleep. Do this by locking the mutex (it is
|
||||||
|
* unlocked) and then locking it again (our waker will
|
||||||
|
* unlock it for us).
|
||||||
|
*/
|
||||||
|
if(pthread_mutex_lock(&v->mutex) != 0)
|
||||||
|
abort();
|
||||||
|
unlock(&v->lk);
|
||||||
|
if(pthread_mutex_lock(&v->mutex) != 0)
|
||||||
|
abort();
|
||||||
|
rval = v->val;
|
||||||
|
pthread_mutex_unlock(&v->mutex);
|
||||||
|
if(DBG)fprint(2, " awake on %p\n", v);
|
||||||
|
unlock(&v->lk);
|
||||||
|
putvous(v);
|
||||||
|
}else{
|
||||||
|
/*
|
||||||
|
* Found someone to meet. Wake him:
|
||||||
|
*
|
||||||
|
* A. lock v->lk (waits for him to lock the mutex once.
|
||||||
|
* B. unlock the mutex (wakes him up)
|
||||||
|
*/
|
||||||
|
if(DBG)fprint(2, "found tag %lux on %p, waking\n", tag, v);
|
||||||
|
lock(&v->lk);
|
||||||
|
rval = v->val;
|
||||||
|
v->val = val;
|
||||||
|
if(pthread_mutex_unlock(&v->mutex) != 0)
|
||||||
|
abort();
|
||||||
|
/* lock passes to him */
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
5
src/libthread/Darwin.c
Normal file
5
src/libthread/Darwin.c
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
int
|
||||||
|
_schedfork(Proc *p)
|
||||||
|
{
|
||||||
|
return ffork(RFMEM|RFNOWAIT, _schedinit, p);
|
||||||
|
}
|
||||||
28
src/libthread/PowerMacintosh.c
Normal file
28
src/libthread/PowerMacintosh.c
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "threadimpl.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
launcherpower(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
|
||||||
|
void (*f)(void *arg), void *arg)
|
||||||
|
{
|
||||||
|
(*f)(arg);
|
||||||
|
threadexits(nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_threadinitstack(Thread *t, void (*f)(void*), void *arg)
|
||||||
|
{
|
||||||
|
ulong *tos, *stk;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
tos = (ulong*)&t->stk[t->stksize&~7];
|
||||||
|
stk = tos;
|
||||||
|
--stk;
|
||||||
|
--stk;
|
||||||
|
--stk;
|
||||||
|
--stk;
|
||||||
|
*--stk = (ulong)arg;
|
||||||
|
*--stk = (ulong)f;
|
||||||
|
t->sched.pc = (ulong)launcherpower+LABELDPC;
|
||||||
|
t->sched.sp = (ulong)tos-80;
|
||||||
|
}
|
||||||
|
|
||||||
80
src/libthread/asm-Darwin-PowerMacintosh.s
Normal file
80
src/libthread/asm-Darwin-PowerMacintosh.s
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
/* get FPR and VR use flags with sc 0x7FF3 */
|
||||||
|
/* get vsave with mfspr reg, 256 */
|
||||||
|
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
.globl __setlabel
|
||||||
|
|
||||||
|
__setlabel: /* xxx: instruction scheduling */
|
||||||
|
mflr r0
|
||||||
|
mfcr r5
|
||||||
|
mfctr r6
|
||||||
|
mfxer r7
|
||||||
|
stw r0, 0*4(r3)
|
||||||
|
stw r5, 1*4(r3)
|
||||||
|
stw r6, 2*4(r3)
|
||||||
|
stw r7, 3*4(r3)
|
||||||
|
|
||||||
|
stw r1, 4*4(r3)
|
||||||
|
stw r2, 5*4(r3)
|
||||||
|
|
||||||
|
stw r13, (0+6)*4(r3) /* callee-save GPRs */
|
||||||
|
stw r14, (1+6)*4(r3) /* xxx: block move */
|
||||||
|
stw r15, (2+6)*4(r3)
|
||||||
|
stw r16, (3+6)*4(r3)
|
||||||
|
stw r17, (4+6)*4(r3)
|
||||||
|
stw r18, (5+6)*4(r3)
|
||||||
|
stw r19, (6+6)*4(r3)
|
||||||
|
stw r20, (7+6)*4(r3)
|
||||||
|
stw r21, (8+6)*4(r3)
|
||||||
|
stw r22, (9+6)*4(r3)
|
||||||
|
stw r23, (10+6)*4(r3)
|
||||||
|
stw r24, (11+6)*4(r3)
|
||||||
|
stw r25, (12+6)*4(r3)
|
||||||
|
stw r26, (13+6)*4(r3)
|
||||||
|
stw r27, (14+6)*4(r3)
|
||||||
|
stw r28, (15+6)*4(r3)
|
||||||
|
stw r29, (16+6)*4(r3)
|
||||||
|
stw r30, (17+6)*4(r3)
|
||||||
|
stw r31, (18+6)*4(r3)
|
||||||
|
|
||||||
|
li r3, 0 /* return */
|
||||||
|
blr
|
||||||
|
|
||||||
|
.globl __gotolabel
|
||||||
|
|
||||||
|
__gotolabel:
|
||||||
|
lwz r13, (0+6)*4(r3) /* callee-save GPRs */
|
||||||
|
lwz r14, (1+6)*4(r3) /* xxx: block move */
|
||||||
|
lwz r15, (2+6)*4(r3)
|
||||||
|
lwz r16, (3+6)*4(r3)
|
||||||
|
lwz r17, (4+6)*4(r3)
|
||||||
|
lwz r18, (5+6)*4(r3)
|
||||||
|
lwz r19, (6+6)*4(r3)
|
||||||
|
lwz r20, (7+6)*4(r3)
|
||||||
|
lwz r21, (8+6)*4(r3)
|
||||||
|
lwz r22, (9+6)*4(r3)
|
||||||
|
lwz r23, (10+6)*4(r3)
|
||||||
|
lwz r24, (11+6)*4(r3)
|
||||||
|
lwz r25, (12+6)*4(r3)
|
||||||
|
lwz r26, (13+6)*4(r3)
|
||||||
|
lwz r27, (14+6)*4(r3)
|
||||||
|
lwz r28, (15+6)*4(r3)
|
||||||
|
lwz r29, (16+6)*4(r3)
|
||||||
|
lwz r30, (17+6)*4(r3)
|
||||||
|
lwz r31, (18+6)*4(r3)
|
||||||
|
|
||||||
|
lwz r1, 4*4(r3)
|
||||||
|
lwz r2, 5*4(r3)
|
||||||
|
|
||||||
|
lwz r0, 0*4(r3)
|
||||||
|
mtlr r0
|
||||||
|
lwz r0, 1*4(r3)
|
||||||
|
mtcr r0 /* mtcrf 0xFF, r0 */
|
||||||
|
lwz r0, 2*4(r3)
|
||||||
|
mtctr r0
|
||||||
|
lwz r0, 3*4(r3)
|
||||||
|
mtxer r0
|
||||||
|
li r3, 1
|
||||||
|
blr
|
||||||
Loading…
Add table
Add a link
Reference in a new issue