diff lwdisasm/range.c @ 409:cba03436c720

Checkpoint disassembler
author lost@l-w.ca
date Mon, 02 Aug 2010 18:07:04 -0600
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwdisasm/range.c	Mon Aug 02 18:07:04 2010 -0600
@@ -0,0 +1,124 @@
+/*
+range.c
+
+Copyright © 2010 William Astle
+
+This file is part of LWTOOLS.
+
+LWTOOLS is free software: you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <lw_alloc.h>
+
+#include "lwdisasm.h"
+
+void register_range(disasmstate_t *as, int min, int max, int type)
+{
+	rangedata_t *nr;
+	rangedata_t *r;
+
+	// first remove any complete subsets of the new range
+subsetagain:
+	for (r = as -> rhead; r; r = r -> next)
+	{
+		// if we haven't run into an existing range yet, short circuit
+		if (r -> min >= min && r -> max <= max)
+		{
+			if (r -> prev)
+				r -> prev -> next = r -> next;
+			else
+				as -> rhead = r -> next;
+			if (r -> next)
+				r -> next -> prev = r -> prev;
+			else
+				as -> rtail = r -> prev;
+			goto subsetagain;
+		}		
+	}
+
+	// now shorten any subset that overlaps below or overlaps above
+	for (r = as -> rhead; r; r = r -> next)
+	{
+		// are we a subset of this range?
+		if (r -> min <= min && r -> max >= max)
+		{
+			// proper subset; split
+			nr = lw_alloc(sizeof(rangedata_t));
+			*nr = *r;
+			r -> next = nr;
+			nr -> prev = r;
+			r -> max = min - 1;
+			nr -> min = max + 1;
+			break;
+		}
+		// overlap above us
+		if (r -> max > max && r -> min < max)
+		{
+			r -> min = max + 1;
+		}
+		// overlap on the bottom
+		if (r -> min < min &&  r -> max > min)
+		{
+			r -> max = min - 1;
+		}
+	}
+	
+	// now add new range
+	for (r = as -> rhead; r; r = r -> next)
+	{
+		if (r -> min < max)
+		{
+			break;
+		}
+	}
+	
+	nr = lw_alloc(sizeof(rangedata_t));
+	nr -> min = min;
+	nr -> max = max;
+	nr -> type = type;
+	
+	if (r)
+	{
+		if (r -> prev)
+			r -> prev -> next = nr;
+		else
+			as -> rhead = nr;
+		nr -> prev = r -> prev;
+		nr -> next = r;
+		r -> prev = nr;
+	}
+	else
+	{
+		nr -> next = NULL;
+		nr -> prev = as -> rtail;
+		as -> rtail -> next = nr;
+		as -> rtail = nr;
+	}
+}
+
+rangedata_t *lookup_range(disasmstate_t *as, int addr)
+{
+	rangedata_t *r;
+	
+	for (r = as -> rhead; r; r = r -> next)
+	{
+		if (r -> min <= addr && r -> max >= addr)
+			return r;
+	}
+	return NULL;
+}