shithub: riscv

Download patch

ref: 9920ecc04b87cab3968f7f0c286b264bd31e132f
parent: 59ff04ddb1b845bfd8542c886bb42c5cb3112a0b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri May 3 16:57:30 EDT 2019

libc: initial arm64 support

diff: cannot open b/arm64/include//null: file does not exist: 'b/arm64/include//null' diff: cannot open b/arm64//null: file does not exist: 'b/arm64//null' diff: cannot open b/sys/src/libc/arm64//null: file does not exist: 'b/sys/src/libc/arm64//null'
--- /dev/null
+++ b/arm64/include/u.h
@@ -1,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])
--- /dev/null
+++ b/arm64/include/ureg.h
@@ -1,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;
--- a/sys/src/libc/9syscall/mkfile
+++ b/sys/src/libc/9syscall/mkfile
@@ -107,6 +107,14 @@
 				MOVW R0,4(R1)'
 			}
 			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
 			echo TEXT $i'(SB)', 1, '$0'
 			echo MOVW R3, '0(FP)'
--- /dev/null
+++ b/sys/src/libc/arm64/_seek.c
@@ -1,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;
+}
--- /dev/null
+++ b/sys/src/libc/arm64/argv0.s
@@ -1,0 +1,4 @@
+GLOBL	argv0(SB), $8
+GLOBL	_tos(SB), $8
+GLOBL	_privates(SB), $8
+GLOBL	_nprivates(SB), $4
--- /dev/null
+++ b/sys/src/libc/arm64/atom.s
@@ -1,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)
--- /dev/null
+++ b/sys/src/libc/arm64/cycles.s
@@ -1,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
--- /dev/null
+++ b/sys/src/libc/arm64/getcallerpc.s
@@ -1,0 +1,3 @@
+TEXT getcallerpc(SB), $0
+	MOV	0(SP), R0
+	RETURN
--- /dev/null
+++ b/sys/src/libc/arm64/getfcr.s
@@ -1,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
+
--- /dev/null
+++ b/sys/src/libc/arm64/lock.c
@@ -1,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);
+}
--- /dev/null
+++ b/sys/src/libc/arm64/main9.s
@@ -1,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
--- /dev/null
+++ b/sys/src/libc/arm64/main9p.s
@@ -1,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
--- /dev/null
+++ b/sys/src/libc/arm64/mkfile
@@ -1,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
--- /dev/null
+++ b/sys/src/libc/arm64/notejmp.c
@@ -1,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);
+}
--- /dev/null
+++ b/sys/src/libc/arm64/setjmp.s
@@ -1,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
--- /dev/null
+++ b/sys/src/libc/arm64/tas.s
@@ -1,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