ref: 6b4a9c5d8d291ce15e9f31cb130537fe47a9688e
parent: 575015d2b023e5707293830186581f03c33aa90a
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Jun 19 10:43:32 EDT 2015
5e: implement DSB,DMB,ISB and CLREX instructions
--- a/sys/src/cmd/5e/5e.c
+++ b/sys/src/cmd/5e/5e.c
@@ -36,6 +36,7 @@
if(P == nil)
return;
+ clrex();
remproc(P);
decref(&nproc);
freesegs();
--- a/sys/src/cmd/5e/arm.c
+++ b/sys/src/cmd/5e/arm.c
@@ -134,6 +134,7 @@
addr = *Rn;
if((instr & fB) == 0)
addr = evenaddr(addr, 3);
+ clrex();
targ = (u32int *) vaddr(addr, 4, &seg);
lock(&seg->lock);
if(instr & fB) {
@@ -400,8 +401,10 @@
invalid(instr);
addr = evenaddr(*Rn, 3);
if(instr & fS) {
+ clrex();
targ = vaddr(addr, 4, &seg);
lock(&seg->lock);
+ P->excl = seg;
*Rd = *targ;
segunlock(seg);
} else {
@@ -410,17 +413,40 @@
invalid(instr);
targ = vaddr(addr, 4, &seg);
if(canlock(&seg->lock)) {
+ unlock(&seg->lock);
*Rd = 1;
+ } else if(P->excl != seg) {
+ *Rd = 1;
} else {
*targ = *Rm;
- unlock(&seg->lock);
*Rd = 0;
}
segunlock(seg);
+ clrex();
}
}
void
+clrex(void)
+{
+ Segment *seg;
+
+ seg = P->excl;
+ P->excl = nil;
+ if(seg != nil)
+ unlock(&seg->lock);
+}
+
+static void
+barrier(void)
+{
+ static Lock l;
+
+ lock(&l);
+ unlock(&l);
+}
+
+void
step(void)
{
u32int instr;
@@ -463,7 +489,18 @@
case 0xC: if((P->CPSR & flZ) || !(P->CPSR & flN) != !(P->CPSR & flV)) return; break;
case 0xD: if(!(P->CPSR & flZ) && !(P->CPSR & flN) == !(P->CPSR & flV)) return; break;
case 0xE: break;
- default: sysfatal("condition code %x not implemented", instr >> 28);
+ case 0xF:
+ switch(instr & 0xFFF000F0){
+ case 0xF5700010: /* CLREX */
+ clrex();
+ return;
+ case 0xF5700040: /* DSB */
+ case 0xF5700050: /* DMB */
+ case 0xF5700060: /* ISB */
+ barrier();
+ return;
+ }
+ default: sysfatal("condition code %x not implemented (instr %ux, ps %ux)", instr >> 28, instr, P->R[15]);
}
if((instr & 0x0FB00FF0) == 0x01000090)
swap(instr);
--- a/sys/src/cmd/5e/dat.h
+++ b/sys/src/cmd/5e/dat.h
@@ -31,9 +31,10 @@
Ref *path; /* Ref + string data */
Segment *S[SEGNUM]; /* memory */
+ Segment *excl; /* recently acquired exclusive access */
u32int R[16]; /* general purpose registers / PC (R15) */
u32int CPSR; /* status register */
-
+
u32int FPSR;
long double F[Nfpregs];
--- a/sys/src/cmd/5e/fns.h
+++ b/sys/src/cmd/5e/fns.h
@@ -17,6 +17,7 @@
int iscexec(Fd *, int);
void setcexec(Fd *, int, int);
void cleanup(void);
+void clrex(void);
void segunlock(Segment *);
void *copyifnec(u32int, int, int *);
void *bufifnec(u32int, int, int *);
--- a/sys/src/cmd/5e/proc.c
+++ b/sys/src/cmd/5e/proc.c
@@ -378,6 +378,7 @@
if(P->notehandler == 0)
exits(msg);
+ clrex();
uregp = P->R[13] - 18 * 4;
ureg = vaddrnol(uregp, 18 * 4);
memcpy(ureg, P->R, 15 * 4);