https://github.com/akkartik/mu/blob/master/subx/034compute_segment_address.cc
1
2
3
4
5 void test_segment_name() {
6 run(
7 "== code\n"
8 "05/add-to-EAX 0x0d0c0b0a/imm32\n"
9
10 );
11 CHECK_TRACE_CONTENTS(
12 "load: 0x09000054 -> 05\n"
13 "load: 0x09000055 -> 0a\n"
14 "load: 0x09000056 -> 0b\n"
15 "load: 0x09000057 -> 0c\n"
16 "load: 0x09000058 -> 0d\n"
17 "run: add imm32 0x0d0c0b0a to reg EAX\n"
18 "run: storing 0x0d0c0b0a\n"
19 );
20 }
21
22
23
24
25
26 :(before "End Globals")
27 map<string, int> Segment_index;
28 bool Currently_parsing_named_segment = false;
29 int Currently_parsing_segment_index = -1;
30 :(before "End Reset")
31 Segment_index.clear();
32 Currently_parsing_named_segment = false;
33 Currently_parsing_segment_index = -1;
34
35 :(before "End Segment Parsing Special-cases(segment_title)")
36 if (!starts_with(segment_title, "0x")) {
37 Currently_parsing_named_segment = true;
38 if (!contains_key(Segment_index, segment_title)) {
39 trace(3, "parse") << "new segment '" << segment_title << "'" << end();
40 if (out.segments.empty() && segment_title != "code") {
41 raise << "first segment must be 'code' but is '" << segment_title << "'\n" << end();
42 return;
43 }
44 if (SIZE(out.segments) == 1 && segment_title != "data") {
45 raise << "second segment must be 'data' but is '" << segment_title << "'\n" << end();
46 return;
47 }
48 put(Segment_index, segment_title, SIZE(out.segments));
49 out.segments.push_back(segment());
50 }
51 else {
52 trace(3, "parse") << "appending to segment '" << segment_title << "'" << end();
53 }
54 Currently_parsing_segment_index = get(Segment_index, segment_title);
55 }
56
57 :(before "End flush(p, lines) Special-cases")
58 if (Currently_parsing_named_segment) {
59 assert(!p.segments.empty());
60 trace(3, "parse") << "flushing segment" << end();
61 vector<line>& curr_segment_data = p.segments.at(Currently_parsing_segment_index).lines;
62 curr_segment_data.insert(curr_segment_data.end(), lines.begin(), lines.end());
63 lines.clear();
64 Currently_parsing_named_segment = false;
65 Currently_parsing_segment_index = -1;
66 return;
67 }
68
69 :(code)
70 void test_repeated_segment_merges_data() {
71 run(
72 "== code\n"
73 "05/add-to-EAX 0x0d0c0b0a/imm32\n"
74 "== code\n"
75 "2d/subtract-from-EAX 0xddccbbaa/imm32\n"
76 );
77 CHECK_TRACE_CONTENTS(
78 "parse: new segment 'code'\n"
79 "parse: appending to segment 'code'\n"
80
81 "load: 0x09000054 -> 05\n"
82 "load: 0x09000055 -> 0a\n"
83 "load: 0x09000056 -> 0b\n"
84 "load: 0x09000057 -> 0c\n"
85 "load: 0x09000058 -> 0d\n"
86
87 "load: 0x09000059 -> 2d\n"
88 "load: 0x0900005a -> aa\n"
89 "load: 0x0900005b -> bb\n"
90 "load: 0x0900005c -> cc\n"
91 "load: 0x0900005d -> dd\n"
92 );
93 }
94
95 void test_error_on_missing_segment_header() {
96 Hide_errors = true;
97 run(
98 "05/add-to-EAX 0/imm32\n"
99 );
100 CHECK_TRACE_CONTENTS(
101 "error: input does not start with a '==' section header\n"
102 );
103 }
104
105 void test_error_on_first_segment_not_code() {
106 Hide_errors = true;
107 run(
108 "== data\n"
109 "05 00 00 00 00\n"
110 );
111 CHECK_TRACE_CONTENTS(
112 "error: first segment must be 'code' but is 'data'\n"
113 );
114 }
115
116 void test_error_on_second_segment_not_data() {
117 Hide_errors = true;
118 run(
119 "== code\n"
120 "05/add-to-EAX 0/imm32\n"
121 "== bss\n"
122 "05 00 00 00 00\n"
123 );
124 CHECK_TRACE_CONTENTS(
125 "error: second segment must be 'data' but is 'bss'\n"
126 );
127 }
128
129
130
131 :(before "End Level-2 Transforms")
132 Transform.push_back(compute_segment_starts);
133
134 :(code)
135 void compute_segment_starts(program& p) {
136 trace(3, "transform") << "-- compute segment addresses" << end();
137 uint32_t p_offset = 0x34 + SIZE(p.segments)*0x20;
138 for (size_t i = 0; i < p.segments.size(); ++i) {
139 segment& curr = p.segments.at(i);
140 if (curr.start == 0) {
141 curr.start = CODE_SEGMENT + i*SPACE_FOR_SEGMENT + p_offset;
142 trace(99, "transform") << "segment " << i << " begins at address 0x" << HEXWORD << curr.start << end();
143 }
144 p_offset += size_of(curr);
145 assert(p_offset < SEGMENT_ALIGNMENT);
146 }
147 }
148
149 uint32_t size_of(const segment& s) {
150 uint32_t sum = 0;
151 for (int i = 0; i < SIZE(s.lines); ++i)
152 sum += num_bytes(s.lines.at(i));
153 return sum;
154 }
155
156
157 uint32_t num_bytes(const line& inst) {
158 uint32_t sum = 0;
159 for (int i = 0; i < SIZE(inst.words); ++i)
160 sum += size_of(inst.words.at(i));
161 return sum;
162 }
163
164 int size_of(const word& w) {
165 if (has_operand_metadata(w, "disp32") || has_operand_metadata(w, "imm32"))
166 return 4;
167 else if (has_operand_metadata(w, "disp16"))
168 return 2;
169
170 else
171 return 1;
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187