diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-06-19 14:43:32 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-06-19 14:43:32 +0200 |
commit | 6b4a9c5d8d291ce15e9f31cb130537fe47a9688e (patch) | |
tree | 49c2c5b854636e3976a28ef9d207ee5ba86e625b /sys/src/cmd/5e/arm.c | |
parent | 575015d2b023e5707293830186581f03c33aa90a (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.c | 41 |
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); |