ref: 9920ecc04b87cab3968f7f0c286b264bd31e132f
parent: 59ff04ddb1b845bfd8542c886bb42c5cb3112a0b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri May 3 16:57:30 EDT 2019
libc: initial arm64 support
--- /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