annotate lwdisasm/range.c @ 414:010fb62b9f18

Fixed off by one bug in code generation for fcn
author lost@l-w.ca
date Tue, 10 Aug 2010 17:33:56 -0600
parents cba03436c720
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
409
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
1 /*
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
2 range.c
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
3
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
4 Copyright © 2010 William Astle
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
5
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
6 This file is part of LWTOOLS.
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
7
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
8 LWTOOLS is free software: you can redistribute it and/or modify it under the
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
9 terms of the GNU General Public License as published by the Free Software
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
10 Foundation, either version 3 of the License, or (at your option) any later
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
11 version.
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
12
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
13 This program is distributed in the hope that it will be useful, but WITHOUT
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
16 more details.
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
17
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
18 You should have received a copy of the GNU General Public License along with
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
19 this program. If not, see <http://www.gnu.org/licenses/>.
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
20 */
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
21
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
22 #include <config.h>
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
23
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
24 #include <stdlib.h>
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
25
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
26 #include <lw_alloc.h>
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
27
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
28 #include "lwdisasm.h"
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
29
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
30 void register_range(disasmstate_t *as, int min, int max, int type)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
31 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
32 rangedata_t *nr;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
33 rangedata_t *r;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
34
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
35 // first remove any complete subsets of the new range
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
36 subsetagain:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
37 for (r = as -> rhead; r; r = r -> next)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
38 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
39 // if we haven't run into an existing range yet, short circuit
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
40 if (r -> min >= min && r -> max <= max)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
41 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
42 if (r -> prev)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
43 r -> prev -> next = r -> next;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
44 else
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
45 as -> rhead = r -> next;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
46 if (r -> next)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
47 r -> next -> prev = r -> prev;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
48 else
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
49 as -> rtail = r -> prev;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
50 goto subsetagain;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
51 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
52 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
53
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
54 // now shorten any subset that overlaps below or overlaps above
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
55 for (r = as -> rhead; r; r = r -> next)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
56 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
57 // are we a subset of this range?
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
58 if (r -> min <= min && r -> max >= max)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
59 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
60 // proper subset; split
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
61 nr = lw_alloc(sizeof(rangedata_t));
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
62 *nr = *r;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
63 r -> next = nr;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
64 nr -> prev = r;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
65 r -> max = min - 1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
66 nr -> min = max + 1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
67 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
68 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
69 // overlap above us
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
70 if (r -> max > max && r -> min < max)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
71 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
72 r -> min = max + 1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
73 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
74 // overlap on the bottom
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
75 if (r -> min < min && r -> max > min)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
76 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
77 r -> max = min - 1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
78 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
79 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
80
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
81 // now add new range
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
82 for (r = as -> rhead; r; r = r -> next)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
83 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
84 if (r -> min < max)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
85 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
86 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
87 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
88 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
89
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
90 nr = lw_alloc(sizeof(rangedata_t));
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
91 nr -> min = min;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
92 nr -> max = max;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
93 nr -> type = type;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
94
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
95 if (r)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
96 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
97 if (r -> prev)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
98 r -> prev -> next = nr;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
99 else
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
100 as -> rhead = nr;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
101 nr -> prev = r -> prev;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
102 nr -> next = r;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
103 r -> prev = nr;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
104 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
105 else
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
106 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
107 nr -> next = NULL;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
108 nr -> prev = as -> rtail;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
109 as -> rtail -> next = nr;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
110 as -> rtail = nr;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
111 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
112 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
113
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
114 rangedata_t *lookup_range(disasmstate_t *as, int addr)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
115 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
116 rangedata_t *r;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
117
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
118 for (r = as -> rhead; r; r = r -> next)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
119 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
120 if (r -> min <= addr && r -> max >= addr)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
121 return r;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
122 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
123 return NULL;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
124 }