summaryrefslogtreecommitdiff
path: root/sys/src/cmd/5e/arm.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2015-06-19 14:43:32 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2015-06-19 14:43:32 +0200
commit6b4a9c5d8d291ce15e9f31cb130537fe47a9688e (patch)
tree49c2c5b854636e3976a28ef9d207ee5ba86e625b /sys/src/cmd/5e/arm.c
parent575015d2b023e5707293830186581f03c33aa90a (diff)
5e: implement DSB,DMB,ISB and CLREX instructions
Diffstat (limited to 'sys/src/cmd/5e/arm.c')
-rw-r--r--sys/src/cmd/5e/arm.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/sys/src/cmd/5e/arm.c b/sys/src/cmd/5e/arm.c
index bbede825c..f824d8a01 100644
--- a/sys/src/cmd/5e/arm.c
+++ b/sys/src/cmd/5e/arm.c
@@ -134,6 +134,7 @@ swap(u32int instr)
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 @@ singleex(u32int instr)
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 @@ singleex(u32int instr)
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 @@ step(void)
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);