Skip to content

Commit

Permalink
Add cmpxchg16b and cmpxchg8b
Browse files Browse the repository at this point in the history
  • Loading branch information
jart committed Apr 7, 2023
1 parent c4bb7d3 commit f49c38d
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 1 deletion.
50 changes: 50 additions & 0 deletions blink/machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "blink/machine.h"
#include "blink/macros.h"
#include "blink/map.h"
#include "blink/modrm.h"
#include "blink/random.h"
#include "blink/signal.h"
#include "blink/sse.h"
Expand Down Expand Up @@ -234,10 +235,59 @@ static void OpXchgZvqp(P) {
WriteRegister(rde, RegRexbSrm(m, rde), x);
}

static void OpCmpxchg8b(P) {
uint8_t *p;
uint32_t d, a;
p = GetModrmRegisterXmmPointerRead8(A);
if (Lock(rde)) LockBus(p);
a = Read32(p + 0);
d = Read32(p + 4);
if (a == Read32(m->ax) && d == Read32(m->dx)) {
m->flags = SetFlag(m->flags, FLAGS_ZF, true);
memcpy(p + 0, m->bx, 4);
memcpy(p + 4, m->cx, 4);
} else {
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
Write32(m->ax, a);
Write32(m->dx, d);
}
if (Lock(rde)) UnlockBus(p);
}

static void OpCmpxchg16b(P) {
uint8_t *p;
uint64_t d, a;
p = GetModrmRegisterXmmPointerRead16(A);
if (Lock(rde)) LockBus(p);
a = Read64(p + 0);
d = Read64(p + 8);
if (a == Read64(m->ax) && d == Read64(m->dx)) {
m->flags = SetFlag(m->flags, FLAGS_ZF, true);
memcpy(p + 0, m->bx, 8);
memcpy(p + 8, m->cx, 8);
} else {
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
Write64(m->ax, a);
Write64(m->dx, d);
}
if (Lock(rde)) UnlockBus(p);
}

static void Op1c7(P) {
bool ismem;
ismem = !IsModrmRegister(rde);
switch (ModrmReg(rde)) {
case 1:
if (ismem) {
if (Rexw(rde)) {
OpCmpxchg16b(A);
} else {
OpCmpxchg8b(A);
}
} else {
OpUdImpl(m);
}
break;
case 6:
if (!ismem) {
OpRdrand(A);
Expand Down
2 changes: 1 addition & 1 deletion test/asm/cmpxchg.S
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ _start:

// compare and exchange tests
// make -j8 o//blink o//test/asm/cmpxchg.elf
// o//blink/tui o//test/asm/cmpxchg.elf
// o//blink/blinkenlights o//test/asm/cmpxchg.elf

xor %ebp,%ebp
and $-16,%rsp
Expand Down
44 changes: 44 additions & 0 deletions test/asm/cmpxchg16b.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "test/asm/mac.inc"
.globl _start
_start:

// compare and exchange tests
// make -j8 o//blink o//test/asm/cmpxchg16b.elf
// o//blink/blinkenlights o//test/asm/cmpxchg16b.elf

mov $0,%rax
mov %rax,-16(%rsp)
mov %rax,-8(%rsp)

.test "lock cmpxchg16b 64 not taken"
// if memory is equal to me
mov $0x5555555155555550,%rdx
mov $0x1234567812345678,%rax
// replace it with me
mov $0x5500005155550050,%rcx
mov $0x1200067810000078,%rbx
lock cmpxchg16b -16(%rsp)
.nz
cmp $0,%rdx
.z
cmp $0,%rax
.z

.test "lock cmpxchg16b 64 taken"
// if memory is equal to me
mov $0x5555555155555550,%rdx
mov $0x1234567812345678,%rax
mov %rax,-16(%rsp)
mov %rdx,-8(%rsp)
// replace it with me
mov $0x5500005155550050,%rcx
mov $0x1200067810000078,%rbx
lock cmpxchg16b -16(%rsp)
.z
cmp %rbx,-16(%rsp)
.z
cmp %rcx,-8(%rsp)
.z

"test succeeded":
.exit

0 comments on commit f49c38d

Please sign in to comment.