Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix several edge case interactions involving page faults #17

Merged
merged 1 commit into from
Mar 14, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 39 additions & 24 deletions src/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,32 +506,36 @@ static uint32_t vm_read_across(vm_t *vm, uint32_t address, int size) {
}

void vm_write_across(vm_t *vm, uint32_t address, int size, uint32_t value) {
// write the first page
// calculate number of bytes for each page

int bytes = 0x1000 - (address & 0x00000FFF);
uint8_t *ptr = vm_findmemory(vm, address, bytes, true);
int bytes_first = 0x1000 - (address & 0x00000FFF);

while (bytes) {
*ptr = value & 0xFF;
int address_second = (address + size) & 0xFFFFF000;
int bytes_second = (address + size) & 0x00000FFF;

// make sure both pages are resident before doing any writing

uint8_t *ptr_first = vm_findmemory(vm, address, bytes_first, true);
uint8_t *ptr_second = vm_findmemory(vm, address_second, bytes_second, true);

// write the first page

while (bytes_first) {
*ptr_first = value & 0xFF;
value >>= 8;

ptr++;
bytes--;
ptr_first++;
bytes_first--;
}

// write the second page

bytes = (address + size) & 0x00000FFF;
address = (address + size) & 0xFFFFF000;

ptr = vm_findmemory(vm, address, bytes, true);

while (bytes) {
*ptr = value & 0xFF;
while (bytes_second) {
*ptr_second = value & 0xFF;
value >>= 8;

ptr++;
bytes--;
ptr_second++;
bytes_second--;
}
}

Expand Down Expand Up @@ -790,9 +794,18 @@ static void vm_skipparam(vm_t *vm, uint32_t size, uint8_t prtype) {
break; \
}

// make sure NOT to update the stack pointer until the full instruction has
// been read, and the target has been written. otherwise a pagefault halfway
// through could wreak havoc.

#define VM_IMPL_POP(_size, _vm_target, _vm_pop) { \
VM_PRELUDE_1(_size); \
_vm_target(vm, instr.source, _vm_pop(vm)); \
uint32_t oldsp = vm->pointer_stack; \
uint32_t val = _vm_pop(vm); \
uint32_t newsp = vm->pointer_stack; \
vm->pointer_stack = oldsp; \
_vm_target(vm, instr.source, val); \
vm->pointer_stack = newsp; \
break; \
}

Expand All @@ -812,18 +825,19 @@ static void vm_skipparam(vm_t *vm, uint32_t size, uint8_t prtype) {
VM_PRELUDE_1(_size); \
_type v = _vm_source_stay(vm, instr.source); \
_type x = ~v; \
vm->flag_zero = x == 0; \
_vm_target(vm, instr.source, x); \
vm->flag_zero = x == 0; \
break; \
}

#define VM_IMPL_INC(_size, _type, _vm_source_stay, _vm_target, _oper) { \
VM_PRELUDE_1(_size); \
_type v = _vm_source_stay(vm, instr.source); \
_type x; \
vm->flag_carry = _oper(v, 1, &x); \
vm->flag_zero = x == 0; \
bool carry = _oper(v, 1, &x); \
_vm_target(vm, instr.source, x); \
vm->flag_carry = carry; \
vm->flag_zero = x == 0; \
break; \
}

Expand All @@ -832,9 +846,10 @@ static void vm_skipparam(vm_t *vm, uint32_t size, uint8_t prtype) {
_type a = (_type) _vm_source(vm, instr.source); \
_type b = (_type) _vm_source_stay(vm, instr.target); \
_type x; \
vm->flag_carry = _oper(b, a, &x); \
vm->flag_zero = x == 0; \
bool carry = _oper(b, a, &x); \
_vm_target(vm, instr.target, (_type_target) x); \
vm->flag_carry = carry; \
vm->flag_zero = x == 0; \
break; \
}

Expand All @@ -843,8 +858,8 @@ static void vm_skipparam(vm_t *vm, uint32_t size, uint8_t prtype) {
_type a = (_type) _vm_source(vm, instr.source); \
_type b = (_type) _vm_source_stay(vm, instr.target); \
_type x = _oper(b, a); \
vm->flag_zero = x == 0; \
_vm_target(vm, instr.target, (_type_target) x); \
vm->flag_zero = x == 0; \
break; \
}

Expand All @@ -857,8 +872,8 @@ static void vm_skipparam(vm_t *vm, uint32_t size, uint8_t prtype) {
break; \
} \
_type x = _oper(b, a); \
vm->flag_zero = x == 0; \
_vm_target(vm, instr.target, (_type_target) x); \
vm->flag_zero = x == 0; \
break; \
}

Expand Down