Binary search for breakpoints

This commit is contained in:
tudnai 2022-11-11 20:56:56 -08:00
parent 6ebb350ec3
commit 042cbb54d4
6 changed files with 1358 additions and 1144 deletions

View File

@ -750,6 +750,7 @@
32D08987291A450400F2B486 /* 6502_bp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 6502_bp.h; sourceTree = "<group>"; };
32D08992291AF23500F2B486 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = A2Mac/Base.lproj/Debug.storyboard; sourceTree = "<group>"; };
32D089D7291E1BF800F2B486 /* DisassView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisassView.swift; sourceTree = "<group>"; };
32D089EC291EE19200F2B486 /* UnfairLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnfairLock.swift; sourceTree = "<group>"; };
32DBF7632334657900DD50E7 /* HiRes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HiRes.swift; sourceTree = "<group>"; };
32DBF76723373FB400DD50E7 /* disassembler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = disassembler.h; sourceTree = "<group>"; };
32E21BE62491BF8B006C0C72 /* apple-rainbow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "apple-rainbow.png"; sourceTree = "<group>"; };
@ -1173,6 +1174,7 @@
children = (
32BFFB5E22EACC660003B53F /* Assets.xcassets */,
32B18438233FAB3900DBB4AB /* verticies.swift */,
32D089EC291EE19200F2B486 /* UnfairLock.swift */,
32BFFB5A22EACC630003B53F /* AppDelegate.swift */,
32B3778E291787CA0040845B /* NSLayoutConstraint.swift */,
32100A8A2875387300D894EE /* CheatMenu.swift */,

View File

@ -50,7 +50,7 @@ class DebuggerViewController: NSViewController {
// // Update window title with the active TableView Title
// self.parent?.view.window?.title = self.title!
Update()
UpdateImmediately()
if let debugger = DebuggerWindowController.current {
debugger.PauseButtonUpdate(needUpdateMainToolbar: false)
@ -242,7 +242,7 @@ N V - B D I Z C
func getLine(inView view: NSTextView, forY: CGFloat) -> Int {
var scrollTo = view.visibleRect.origin
// var scrollTo = view.visibleRect.origin
let lineSpacing = CGFloat(1.5)
let lineHeight = view.font!.pointSize * lineSpacing
@ -328,6 +328,7 @@ N V - B D I Z C
}
let textViewMouseYOffset = CGFloat(-4.0)
func convertMouseCoordinates(scrollView : NSView, display : NSTextView, mouseLocation : NSPoint) -> NSPoint {
var location = mouseLocation
let parent_frame = scrollView.superview?.frame
@ -338,7 +339,7 @@ N V - B D I Z C
let maxY = minY + scrollView.frame.height
// location.x = maxX - location.x
location.y = maxY - location.y + display.visibleRect.origin.y
location.y = maxY - location.y + display.visibleRect.origin.y + textViewMouseYOffset
return location
}
@ -411,7 +412,6 @@ N V - B D I Z C
func DisplayDisassembly( scrollY : CGFloat = -1 ) {
let m6502_saved = m6502
var disass = ""
line_number = 0
@ -423,14 +423,15 @@ N V - B D I Z C
// TODO: Also check if memory area updated!
var need_disass = m6502.PC < disass_addr || m6502.PC > disass_addr + disass_addr_max
line_number_at_PC = getLine(forAddr: m6502_saved.PC)
var need_disass = m6502.PC <= disass_addr || m6502.PC > disass_addr + disass_addr_max
line_number_at_PC = getLine(forAddr: m6502.PC)
// if m6502.PC > disass_addr && m6502.PC < disass_addr + disass_addr_max {
if line_number_at_PC != 0 && !need_disass {
m6502.PC = disass_addr
}
else {
if line_number_at_PC == 0 || need_disass {
ViewController.current?.UpdateSemaphore.wait()
let m6502_saved = m6502
need_disass = true
addr_line.removeAll()
@ -467,6 +468,9 @@ N V - B D I Z C
disass += line + "\n"
}
m6502 = m6502_saved
ViewController.current?.UpdateSemaphore.signal()
}
DispatchQueue.main.async {
@ -498,21 +502,24 @@ N V - B D I Z C
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
// your code here
// }
m6502 = m6502_saved
}
func UpdateImmediately() {
DisplayRegisters()
DisplayStack()
DisplayMemory()
DisplayDisassembly()
}
let UpdateSemaphore = DispatchSemaphore(value: 1)
func Update() {
DispatchQueue.global().async {
self.UpdateSemaphore.wait()
self.DisplayRegisters()
self.DisplayStack()
self.DisplayMemory()
self.DisplayDisassembly()
self.UpdateSemaphore.signal()
if self.UpdateSemaphore.wait(timeout: .now()) == .success {
self.UpdateImmediately()
self.UpdateSemaphore.signal()
}
}
}

32
A2Mac/UnfairLock.swift Normal file
View File

@ -0,0 +1,32 @@
//
// UnfairLock.swift
// A2Mac
//
// Created by Tamas Rudnai on 11/11/22.
// Copyright © 2022 GameAlloy. All rights reserved.
//
// Read http://www.russbishop.net/the-law for more information on why this is necessary
final class UnfairLock {
private var _lock: UnsafeMutablePointer<os_unfair_lock>
init() {
_lock = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
_lock.initialize(to: os_unfair_lock())
}
deinit {
_lock.deallocate()
}
func locked<ReturnValue>(_ f: () throws -> ReturnValue) rethrows -> ReturnValue {
os_unfair_lock_lock(_lock)
defer { os_unfair_lock_unlock(_lock) }
return try f()
}
}
//let lock = UnfairLock()
//lock.locked {
// // Critical region
//}

View File

@ -1279,7 +1279,6 @@ class ViewController: NSViewController {
func Update() {
if UpdateSemaphore.wait(timeout: .now() + 0.001) == .timedOut {
// get back here next time...
print("UpdateSemaphore.wait")
return
}

View File

@ -29,19 +29,90 @@
//
#include <string.h>
#include <stdlib.h>
#include "6502_bp.h"
uint16_t breakpoints[DEBUG_MAX_BREAKPOINTS];
int bp_last_idx = 0;
int bp_idx = 0;
void m6502_dbg_bp_swap(uint16_t * a, uint16_t * b) {
uint16_t temp = *a;
*a = *b;
*b = temp;
}
void m6502_dbg_bp_sort( uint16_t arr[], int first, int last ) {
int i, j;
uint16_t pivot;
if ( first < last ) {
pivot = first; // (first + last) / 2;
i = first;
j = last;
while ( i < j ) {
while ( arr[i] <= arr[pivot] && i < last ) {
i++;
}
while ( arr[j] > arr[pivot] && j > first ) {
j--;
}
if ( i < j ) {
m6502_dbg_bp_swap(breakpoints + i, breakpoints + j);
}
}
m6502_dbg_bp_swap(breakpoints + pivot, breakpoints + j);
if (j > first) {
m6502_dbg_bp_sort( arr, first, j - 1 );
}
if (j < last) {
m6502_dbg_bp_sort( arr, j + 1, last );
}
}
}
/// A recursive binary search function. It returns
/// location of addr in given array arr[l..r] is present,
/// otherwise -1
int m6502_dbg_bp_search(uint16_t arr[], int l, int r, uint16_t addr) {
if ( (r >= l) && (addr >= arr[l]) && (addr <= arr[r]) ) {
int mid = (l + r) / 2;
// found it
if (arr[mid] == addr) {
return mid;
}
// maybe in the left side?
if (arr[mid] > addr) {
return m6502_dbg_bp_search(arr, l, mid - 1, addr);
}
// maybe in the right side?
return m6502_dbg_bp_search(arr, mid + 1, r, addr);
}
// addr not found
return -1;
}
/// m6502_dbg_bp_get_empty
/// Get an empty slot in the bp astorage
/// @return Index of the empty breakpoint or -1 if error
int m6502_dbg_bp_get_empty() {
for (int i = 0; i < DEBUG_MAX_BREAKPOINTS; i++) {
if ( breakpoints[i] == 0 ) {
int m6502_dbg_bp_get_last(int i) {
i++;
while(--i) {
if ( breakpoints[i] ) {
return i;
}
}
@ -54,7 +125,7 @@ int m6502_dbg_bp_get_empty() {
/// Get first valid BP
/// @return addr of BP or 0 if non
uint16_t m6502_dbg_bp_get_next() {
while ( bp_idx < DEBUG_MAX_BREAKPOINTS ) {
while ( bp_idx < bp_last_idx ) {
uint16_t addr = breakpoints[++bp_idx];
if (addr) {
return addr;
@ -74,17 +145,54 @@ uint16_t m6502_dbg_bp_get_first() {
}
/// m6502_dbg_bp_get_empty
/// Get an empty slot in the bp storage
/// @return Index of the empty breakpoint or -1 if error
int m6502_dbg_bp_get_empty() {
for (int i = 0; i < DEBUG_MAX_BREAKPOINTS; i++) {
if ( breakpoints[i] == 0 ) {
return i;
}
}
// no empty slots
return -1;
}
/// m6502_dbg_bp_get_not_empty
/// Get first not empty slot in the bp storage
/// @return Index of the empty breakpoint or -1 if error
int m6502_dbg_bp_get_not_empty() {
for (int i = 0; i < DEBUG_MAX_BREAKPOINTS; i++) {
if ( breakpoints[i] ) {
return i;
}
}
// no empty slots
return -1;
}
/// m6502_dbg_bp_compact
/// move array down to eliminate
void m6502_dbg_bp_compact() {
int i = m6502_dbg_bp_get_not_empty();
memcpy(breakpoints, breakpoints + i, bp_last_idx);
memset(breakpoints + bp_last_idx + 1, 0, DEBUG_MAX_BREAKPOINTS - bp_last_idx - 1);
bp_last_idx = m6502_dbg_bp_get_last(bp_last_idx);
}
/// m6502_dbg_bp_get_first
/// Get first valid BP
/// @return addr of BP or 0 if non
_Bool m6502_dbg_bp_is_exists(uint16_t addr) {
for (uint16_t bp = m6502_dbg_bp_get_first(); bp; bp = m6502_dbg_bp_get_next()) {
if ( bp == addr) {
// found it!
return 1;
}
if (addr) {
int i = m6502_dbg_bp_search(breakpoints, 0, bp_last_idx, addr);
return i >= 0;
}
return 0;
else return 0;
}
@ -96,6 +204,10 @@ int m6502_dbg_bp_add(uint16_t addr) {
int i = m6502_dbg_bp_get_empty();
if ( i >= 0 ) {
breakpoints[i] = addr;
if (i > bp_last_idx) {
bp_last_idx = i;
}
m6502_dbg_bp_sort(breakpoints, 0, bp_last_idx);
return i;
}
// no empty slots
@ -110,6 +222,9 @@ void m6502_dbg_bp_del(uint16_t addr) {
for (uint16_t bp = m6502_dbg_bp_get_first(); bp; bp = m6502_dbg_bp_get_next()) {
if ( bp == addr ) {
breakpoints[bp_idx] = 0;
m6502_dbg_bp_sort(breakpoints, 0, bp_last_idx);
m6502_dbg_bp_compact();
// bp_last_idx = m6502_dbg_bp_get_last(bp_last_idx);
}
}
}