libc: initial arm64 support

This commit is contained in:
cinap_lenrek 2019-05-03 20:57:30 +02:00
parent 59ff04ddb1
commit 9920ecc04b
16 changed files with 407 additions and 0 deletions

77
arm64/include/u.h Normal file
View file

@ -0,0 +1,77 @@
#define nil ((void*)0)
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef unsigned long ulong;
typedef unsigned int uint;
typedef signed char schar;
typedef long long vlong;
typedef unsigned long long uvlong;
typedef vlong intptr;
typedef uvlong uintptr;
typedef unsigned long usize;
typedef uint Rune;
typedef union FPdbleword FPdbleword;
typedef uintptr jmp_buf[2];
#define JMPBUFSP 0
#define JMPBUFPC 1
#define JMPBUFDPC 0
typedef unsigned int mpdigit; /* for /sys/include/mp.h */
typedef unsigned char u8int;
typedef unsigned short u16int;
typedef unsigned int u32int;
typedef unsigned long long u64int;
typedef signed char s8int;
typedef signed short s16int;
typedef signed int s32int;
typedef signed long long s64int;
/* FPCR (control) */
#define FPINEX (1<<12)
#define FPUNFL (1<<11)
#define FPOVFL (1<<10)
#define FPZDIV (1<<9)
#define FPINVAL (1<<8)
#define FPRNR (0<<22)
#define FPRPINF (1<<22)
#define FPRNINF (2<<22)
#define FPRZ (3<<22)
#define FPRMASK (3<<22)
/* FPSR (status) */
#define FPPEXT 0
#define FPPSGL 0
#define FPPDBL 0
#define FPPMASK 0
#define FPAINEX (1<<4)
#define FPAUNFL (1<<3)
#define FPAOVFL (1<<2)
#define FPAZDIV (1<<1)
#define FPAINVAL (1<<0)
union FPdbleword
{
double x;
struct { /* little endian */
ulong lo;
ulong hi;
};
};
typedef char* va_list;
#define va_start(list, start) list =\
(sizeof(start) < 8?\
(char*)((vlong*)&(start)+1):\
(char*)(&(start)+1))
#define va_end(list)\
USED(list)
#define va_arg(list, mode)\
((sizeof(mode) == 1)?\
((list += 8), (mode*)list)[-8]:\
(sizeof(mode) == 2)?\
((list += 8), (mode*)list)[-4]:\
(sizeof(mode) == 4)?\
((list += 8), (mode*)list)[-2]:\
((list += sizeof(mode)), (mode*)list)[-1])

40
arm64/include/ureg.h Normal file
View file

@ -0,0 +1,40 @@
typedef struct Ureg {
u64int r0;
u64int r1;
u64int r2;
u64int r3;
u64int r4;
u64int r5;
u64int r6;
u64int r7;
u64int r8;
u64int r9;
u64int r10;
u64int r11;
u64int r12;
u64int r13;
u64int r14;
u64int r15;
u64int r16;
u64int r17;
u64int r18;
u64int r19;
u64int r20;
u64int r21;
u64int r22;
u64int r23;
u64int r24;
u64int r25;
u64int r26;
u64int r27;
u64int r28; /* sb */
u64int r29;
union {
u64int r30;
u64int link;
};
u64int sp;
u64int pc; /* interrupted addr */
u64int psr;
u64int type; /* of exception */
} Ureg;

View file

@ -107,6 +107,14 @@ install:V:
MOVW R0,4(R1)' MOVW R0,4(R1)'
} }
echo RET echo RET
case arm64
j=$i
if(~ $i seek) j=_seek
echo TEXT $j'(SB)', 1, '$0'
echo MOV R0, '0(FP)'
echo MOV '$'$n, R0
echo SVC
echo RETURN
case power case power
echo TEXT $i'(SB)', 1, '$0' echo TEXT $i'(SB)', 1, '$0'
echo MOVW R3, '0(FP)' echo MOVW R3, '0(FP)'

View file

@ -0,0 +1,14 @@
#include <u.h>
#include <libc.h>
extern int _seek(vlong*, int, vlong, int);
vlong
seek(int fd, vlong o, int p)
{
vlong l;
if(_seek(&l, fd, o, p) < 0)
l = -1LL;
return l;
}

View file

@ -0,0 +1,4 @@
GLOBL argv0(SB), $8
GLOBL _tos(SB), $8
GLOBL _privates(SB), $8
GLOBL _nprivates(SB), $4

54
sys/src/libc/arm64/atom.s Normal file
View file

@ -0,0 +1,54 @@
/*
* int cas32(u32int *p, u32int ov, u32int nv);
* int cas(uint *p, int ov, int nv);
* int casl(ulong *p, ulong ov, ulong nv);
*/
TEXT cas32(SB), 1, $-4
TEXT cas(SB), 1, $-4
TEXT casl(SB), 1, $-4
MOVWU ov+8(FP), R1
MOVWU nv+16(FP), R2
_cas1:
LDXRW (R0), R3
CMP R3, R1
BNE _cas0
STXRW R2, (R0), R4
CBNZ R4, _cas1
MOVW $1, R0
B _barrier(SB)
_cas0:
CLREX
MOVW $0, R0
RETURN
TEXT casp(SB), 1, $-4
MOV ov+8(FP), R1
MOV nv+16(FP), R2
_casp1:
LDXR (R0), R3
CMP R3, R1
BNE _cas0
STXR R2, (R0), R4
CBNZ R4, _casp1
MOVW $1, R0
B _barrier(SB)
TEXT _xinc(SB), 1, $-4 /* void _xinc(long *); */
TEXT ainc(SB), 1, $-4 /* long ainc(long *); */
spinainc:
LDXRW (R0), R3
ADDW $1,R3
STXRW R3, (R0), R4
CBNZ R4, spinainc
MOVW R3, R0
B _barrier(SB)
TEXT _xdec(SB), 1, $-4 /* long _xdec(long *); */
TEXT adec(SB), 1, $-4 /* long adec(long *); */
spinadec:
LDXRW (R0), R3
SUBW $1,R3
STXRW R3, (R0), R4
CBNZ R4, spinadec
MOVW R3, R0
B _barrier(SB)

View file

@ -0,0 +1,7 @@
#define SYSREG(op0,op1,Cn,Cm,op2) SPR(((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5))
#define PMCCNTR_EL0 SYSREG(3,3,9,13,0)
TEXT cycles(SB), 1, $-4
MRS PMCCNTR_EL0, R1
MOV R1, (R0)
RETURN

View file

@ -0,0 +1,3 @@
TEXT getcallerpc(SB), $0
MOV 0(SP), R0
RETURN

View file

@ -0,0 +1,21 @@
#define SYSARG5(op0,op1,Cn,Cm,op2) ((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)
#define FPCR SPR(SYSARG5(3,3,4,4,0))
#define FPSR SPR(SYSARG5(3,3,4,4,1))
TEXT setfcr(SB), 1, $-4
MSR R0, FPCR
RETURN
TEXT getfcr(SB), 1, $-4
MRS FPCR, R0
RETURN
TEXT getfsr(SB), 1, $-4
MRS FPSR, R0
RETURN
TEXT setfsr(SB), 1, $-4
MSR R0, FPSR
RETURN

41
sys/src/libc/arm64/lock.c Normal file
View file

@ -0,0 +1,41 @@
#include <u.h>
#include <libc.h>
extern uintptr _barrier(uintptr);
void
lock(Lock *lk)
{
int i;
/* once fast */
if(!_tas(&lk->val))
return;
/* a thousand times pretty fast */
for(i=0; i<1000; i++){
if(!_tas(&lk->val))
return;
sleep(0);
}
/* now nice and slow */
for(i=0; i<1000; i++){
if(!_tas(&lk->val))
return;
sleep(100);
}
/* take your time */
while(_tas(&lk->val))
sleep(1000);
}
int
canlock(Lock *lk)
{
return _tas(&lk->val) == 0;
}
void
unlock(Lock *lk)
{
lk->val = _barrier(0);
}

View file

@ -0,0 +1,25 @@
#define NPRIVATES 16
TEXT _main(SB), 1, $(16 + NPRIVATES*8)
MOV $setSB(SB), R28
MOV R0, _tos(SB)
ADD $32, RSP, R1
MOV R1, _privates(SB)
MOVW $NPRIVATES, R2
MOVW R2, _nprivates(SB)
MOV $inargv+0(FP), R1
MOV R1, 16(RSP)
MOVW inargc-8(FP), R0
MOV R0, 8(RSP)
BL main(SB)
loop:
MOV $_exitstr<>(SB), R0
BL exits(SB)
B loop
DATA _exitstr<>+0(SB)/4, $"main"
GLOBL _exitstr<>+0(SB), $5

View file

@ -0,0 +1,38 @@
#define NPRIVATES 16
TEXT _mainp(SB), 1, $(16 + NPRIVATES*8)
MOV $setSB(SB), R28
MOV R0, _tos(SB)
ADD $32, RSP, R1
MOV R1, _privates(SB)
MOVW $NPRIVATES, R2
MOVW R2, _nprivates(SB)
BL _profmain(SB)
MOV _tos(SB), R0 /* _tos->prof.pp = _tos->prof.next; */
MOV 8(R0), R1
MOV R1, 0(R0)
MOV $inargv+0(FP), R1
MOV R1, 16(RSP)
MOVW inargc-8(FP), R0
MOV R0, 8(RSP)
BL main(SB)
loop:
MOV $_exitstr<>(SB), R0
BL exits(SB)
MOV $_profin(SB), R0
B loop
TEXT _callpc(SB), 1, $-4
MOV 0(SP), R0
TEXT _saveret(SB), 1, $-4
TEXT _savearg(SB), 1, $-4
RETURN
DATA _exitstr<>+0(SB)/4, $"main"
GLOBL _exitstr<>+0(SB), $5

31
sys/src/libc/arm64/mkfile Normal file
View file

@ -0,0 +1,31 @@
objtype=arm64
</$objtype/mkfile
OS=7
LIB=/$objtype/lib/libc.a
SFILES=\
argv0.s\
atom.s\
cycles.s\
getcallerpc.s\
getfcr.s\
main9.s\
main9p.s\
setjmp.s\
tas.s\
CFILES=\
lock.c\
notejmp.c\
_seek.c\
HFILES=/sys/include/libc.h
OFILES=${CFILES:%.c=%.$O} ${SFILES:%.s=%.$O}
UPDATE=mkfile\
$HFILES\
$CFILES\
$SFILES\
</sys/src/cmd/mksyslib

View file

@ -0,0 +1,16 @@
#include <u.h>
#include <libc.h>
#include <ureg.h>
void
notejmp(void *vr, jmp_buf j, int ret)
{
struct Ureg *r = vr;
r->r0 = ret;
if(ret == 0)
r->r0 = 1;
r->pc = j[JMPBUFPC];
r->sp = j[JMPBUFSP];
noted(NCONT);
}

View file

@ -0,0 +1,17 @@
TEXT setjmp(SB), 1, $-4
MOV LR, 8(R0)
MOV SP, R1
MOV R1, 0(R0)
MOV $0, R0
RETURN
TEXT longjmp(SB), 1, $-4
MOV 8(R0), LR
MOV 0(R0), R1
MOVW arg+8(FP), R0
MOV R1, SP
CBZ R0, _one
RETURN
_one:
MOV $1, R0
RETURN

11
sys/src/libc/arm64/tas.s Normal file
View file

@ -0,0 +1,11 @@
TEXT _tas(SB), 1, $-4
MOVW $1, R2
_tas1:
LDXRW (R0), R1
STXRW R2, (R0), R3
CBNZ R3, _tas1
MOVW R1, R0
TEXT _barrier(SB), 1, $-4
DMB $0xB // ISH
RETURN