diff --git a/arm64/include/u.h b/arm64/include/u.h new file mode 100644 index 000000000..94d9cc3b7 --- /dev/null +++ b/arm64/include/u.h @@ -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]) diff --git a/arm64/include/ureg.h b/arm64/include/ureg.h new file mode 100644 index 000000000..02aae42de --- /dev/null +++ b/arm64/include/ureg.h @@ -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; diff --git a/sys/src/libc/9syscall/mkfile b/sys/src/libc/9syscall/mkfile index f8df482bc..48417e271 100644 --- a/sys/src/libc/9syscall/mkfile +++ b/sys/src/libc/9syscall/mkfile @@ -107,6 +107,14 @@ install:V: 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)' diff --git a/sys/src/libc/arm64/_seek.c b/sys/src/libc/arm64/_seek.c new file mode 100644 index 000000000..d44420db2 --- /dev/null +++ b/sys/src/libc/arm64/_seek.c @@ -0,0 +1,14 @@ +#include +#include + +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; +} diff --git a/sys/src/libc/arm64/argv0.s b/sys/src/libc/arm64/argv0.s new file mode 100644 index 000000000..fe4eb4c85 --- /dev/null +++ b/sys/src/libc/arm64/argv0.s @@ -0,0 +1,4 @@ +GLOBL argv0(SB), $8 +GLOBL _tos(SB), $8 +GLOBL _privates(SB), $8 +GLOBL _nprivates(SB), $4 diff --git a/sys/src/libc/arm64/atom.s b/sys/src/libc/arm64/atom.s new file mode 100644 index 000000000..f1fbc522a --- /dev/null +++ b/sys/src/libc/arm64/atom.s @@ -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) diff --git a/sys/src/libc/arm64/cycles.s b/sys/src/libc/arm64/cycles.s new file mode 100644 index 000000000..389ea201f --- /dev/null +++ b/sys/src/libc/arm64/cycles.s @@ -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 diff --git a/sys/src/libc/arm64/getcallerpc.s b/sys/src/libc/arm64/getcallerpc.s new file mode 100644 index 000000000..7ca9a3e8c --- /dev/null +++ b/sys/src/libc/arm64/getcallerpc.s @@ -0,0 +1,3 @@ +TEXT getcallerpc(SB), $0 + MOV 0(SP), R0 + RETURN diff --git a/sys/src/libc/arm64/getfcr.s b/sys/src/libc/arm64/getfcr.s new file mode 100644 index 000000000..c5c90de90 --- /dev/null +++ b/sys/src/libc/arm64/getfcr.s @@ -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 + diff --git a/sys/src/libc/arm64/lock.c b/sys/src/libc/arm64/lock.c new file mode 100644 index 000000000..307c4b7d6 --- /dev/null +++ b/sys/src/libc/arm64/lock.c @@ -0,0 +1,41 @@ +#include +#include + +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); +} diff --git a/sys/src/libc/arm64/main9.s b/sys/src/libc/arm64/main9.s new file mode 100644 index 000000000..36cf953cc --- /dev/null +++ b/sys/src/libc/arm64/main9.s @@ -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 diff --git a/sys/src/libc/arm64/main9p.s b/sys/src/libc/arm64/main9p.s new file mode 100644 index 000000000..0255f3a82 --- /dev/null +++ b/sys/src/libc/arm64/main9p.s @@ -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 diff --git a/sys/src/libc/arm64/mkfile b/sys/src/libc/arm64/mkfile new file mode 100644 index 000000000..b0c7abe06 --- /dev/null +++ b/sys/src/libc/arm64/mkfile @@ -0,0 +1,31 @@ +objtype=arm64 + +#include +#include + +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); +} diff --git a/sys/src/libc/arm64/setjmp.s b/sys/src/libc/arm64/setjmp.s new file mode 100644 index 000000000..741a52a04 --- /dev/null +++ b/sys/src/libc/arm64/setjmp.s @@ -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 diff --git a/sys/src/libc/arm64/tas.s b/sys/src/libc/arm64/tas.s new file mode 100644 index 000000000..090037c81 --- /dev/null +++ b/sys/src/libc/arm64/tas.s @@ -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