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