From 7328af20a1921d9258a60803ee5367da97a6082e Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 13 Aug 2018 21:25:22 -0700 Subject: 4521 --- html/subx/011run.cc.html | 256 +++++++++++++++++++++++++++-------------------- 1 file changed, 148 insertions(+), 108 deletions(-) (limited to 'html/subx/011run.cc.html') diff --git a/html/subx/011run.cc.html b/html/subx/011run.cc.html index 0248497c..653447d6 100644 --- a/html/subx/011run.cc.html +++ b/html/subx/011run.cc.html @@ -16,6 +16,7 @@ a { color:#eeeeee; text-decoration: none; } a:hover { text-decoration: underline; } * { font-size: 12pt; font-size: 1em; } .Constant { color: #00a0a0; } +.Special { color: #c00000; } .SalientComment { color: #00ffff; } .Comment { color: #9090ff; } .Comment a { color:#0000ee; text-decoration:underline; } @@ -71,7 +72,7 @@ if ('onhashchange' in window) { 9 "Line-endings are significant; each line should contain a single\n" 10 "instruction, macro or directive.\n" 11 "\n" - 12 "Comments start with the '#' character. It should be at the start of a word\n" + 12 "Comments start with the '#' character. It should be at the start of a word\n" 13 "(start of line, or following a space).\n" 14 "\n" 15 "Each segment starts with a header line: a '==' delimiter followed by the\n" @@ -133,7 +134,7 @@ if ('onhashchange' in window) { 71 +load: 0x00000003 -> 0b 72 +load: 0x00000004 -> 0c 73 +load: 0x00000005 -> 0d - 74 +run: add imm32 0x0d0c0b0a to reg EAX + 74 +run: add imm32 0x0d0c0b0a to reg EAX 75 +run: storing 0x0d0c0b0a 76 77 :(code) @@ -142,14 +143,14 @@ if ('onhashchange' in window) { 80 void run(const string& text_bytes) { 81 program p; 82 istringstream in(text_bytes); - 83 parse(in, p); - 84 if (trace_contains_errors()) return; // if any stage raises errors, stop immediately - 85 transform(p); - 86 if (trace_contains_errors()) return; + 83 parse(in, p); + 84 if (trace_contains_errors()) return; // if any stage raises errors, stop immediately + 85 transform(p); + 86 if (trace_contains_errors()) return; 87 load(p); - 88 if (trace_contains_errors()) return; - 89 while (EIP < End_of_program) - 90 run_one_instruction(); + 88 if (trace_contains_errors()) return; + 89 while (EIP < End_of_program) + 90 run_one_instruction(); 91 } 92 93 //:: core data structures @@ -172,70 +173,70 @@ if ('onhashchange' in window) { 110 struct line { 111 vector<word> words; 112 vector<string> metadata; -113 }; -114 :(before "struct line") -115 struct word { -116 string original; -117 string data; -118 vector<string> metadata; -119 }; -120 -121 //:: parse -122 -123 :(code) -124 void parse(istream& fin, program& out) { -125 vector<line> l; -126 trace(99, "parse") << "begin" << end(); -127 while (has_data(fin)) { -128 string line_data; -129 getline(fin, line_data); -130 trace(99, "parse") << "line: " << line_data << end(); -131 istringstream lin(line_data); -132 vector<word> w; -133 while (has_data(lin)) { -134 string word_data; -135 lin >> word_data; -136 if (word_data.empty()) continue; -137 if (word_data[0] == '#') break; // comment -138 if (word_data == ".") continue; // comment token -139 if (word_data == "==") { -140 if (!l.empty()) { -141 assert(!out.segments.empty()); -142 trace(99, "parse") << "flushing to segment" << end(); -143 out.segments.back().lines.swap(l); -144 } -145 segment s; -146 lin >> std::hex >> s.start; -147 trace(99, "parse") << "new segment from " << HEXWORD << s.start << end(); -148 out.segments.push_back(s); -149 // todo? -150 break; // skip rest of line -151 } -152 if (word_data[0] == ':') { -153 // todo: line metadata -154 break; -155 } -156 w.push_back(word()); -157 w.back().original = word_data; -158 istringstream win(word_data); -159 if (getline(win, w.back().data, '/')) { -160 string m; -161 while (getline(win, m, '/')) -162 w.back().metadata.push_back(m); -163 } -164 trace(99, "parse") << "new word: " << w.back().data << end(); -165 } -166 if (!w.empty()) { -167 l.push_back(line()); -168 l.back().words.swap(w); -169 } +113 string original; +114 }; +115 :(before "struct line") +116 struct word { +117 string original; +118 string data; +119 vector<string> metadata; +120 }; +121 +122 //:: parse +123 +124 :(code) +125 void parse(istream& fin, program& out) { +126 vector<line> l; +127 trace(99, "parse") << "begin" << end(); +128 while (has_data(fin)) { +129 string line_data; +130 line curr; +131 getline(fin, line_data); +132 curr.original = line_data; +133 trace(99, "parse") << "line: " << line_data << end(); +134 istringstream lin(line_data); +135 while (has_data(lin)) { +136 string word_data; +137 lin >> word_data; +138 if (word_data.empty()) continue; +139 if (word_data[0] == '#') break; // comment +140 if (word_data == ".") continue; // comment token +141 if (word_data == "==") { +142 if (!l.empty()) { +143 assert(!out.segments.empty()); +144 trace(99, "parse") << "flushing to segment" << end(); +145 out.segments.back().lines.swap(l); +146 } +147 segment s; +148 lin >> std::hex >> s.start; +149 trace(99, "parse") << "new segment from " << HEXWORD << s.start << end(); +150 out.segments.push_back(s); +151 // todo? +152 break; // skip rest of line +153 } +154 if (word_data[0] == ':') { +155 // todo: line metadata +156 break; +157 } +158 curr.words.push_back(word()); +159 curr.words.back().original = word_data; +160 istringstream win(word_data); +161 if (getline(win, curr.words.back().data, '/')) { +162 string m; +163 while (getline(win, m, '/')) +164 curr.words.back().metadata.push_back(m); +165 } +166 trace(99, "parse") << "new word: " << curr.words.back().data << end(); +167 } +168 if (!curr.words.empty()) +169 l.push_back(curr); 170 } 171 if (!l.empty()) { 172 assert(!out.segments.empty()); -173 trace(99, "parse") << "flushing to segment" << end(); +173 trace(99, "parse") << "flushing to segment" << end(); 174 out.segments.back().lines.swap(l); 175 } -176 trace(99, "parse") << "done" << end(); +176 trace(99, "parse") << "done" << end(); 177 } 178 179 //:: transform @@ -245,80 +246,119 @@ if ('onhashchange' in window) { 183 :(before "End Globals") 184 vector<transform_fn> Transform; 185 -186 void transform(program& p) { -187 trace(99, "transform") << "begin" << end(); +186 void transform(program& p) { +187 trace(99, "transform") << "begin" << end(); 188 for (int t = 0; t < SIZE(Transform); ++t) 189 (*Transform.at(t))(p); -190 trace(99, "transform") << "done" << end(); +190 trace(99, "transform") << "done" << end(); 191 } 192 193 //:: load 194 195 void load(const program& p) { -196 trace(99, "load") << "begin" << end(); +196 trace(99, "load") << "begin" << end(); 197 if (p.segments.empty()) { -198 raise << "no code to run\n" << end(); +198 raise << "no code to run\n" << end(); 199 return; 200 } 201 for (int i = 0; i < SIZE(p.segments); ++i) { 202 const segment& seg = p.segments.at(i); 203 uint32_t addr = seg.start; -204 trace(99, "load") << "loading segment " << i << " from " << HEXWORD << addr << end(); +204 trace(99, "load") << "loading segment " << i << " from " << HEXWORD << addr << end(); 205 for (int j = 0; j < SIZE(seg.lines); ++j) { 206 const line& l = seg.lines.at(j); 207 for (int k = 0; k < SIZE(l.words); ++k) { 208 const word& w = l.words.at(k); -209 uint8_t val = hex_byte(w.data); -210 if (trace_contains_errors()) return; -211 write_mem_u8(addr, val); -212 trace(99, "load") << "0x" << HEXWORD << addr << " -> " << HEXBYTE << NUM(read_mem_u8(addr)) << end(); +209 uint8_t val = hex_byte(w.data); +210 if (trace_contains_errors()) return; +211 write_mem_u8(addr, val); +212 trace(99, "load") << "0x" << HEXWORD << addr << " -> " << HEXBYTE << NUM(read_mem_u8(addr)) << end(); 213 ++addr; 214 } 215 } -216 if (i == 0) End_of_program = addr; +216 if (i == 0) End_of_program = addr; 217 } -218 EIP = p.segments.at(0).start; -219 trace(99, "load") << "done" << end(); +218 EIP = p.segments.at(0).start; +219 trace(99, "load") << "done" << end(); 220 } 221 222 uint8_t hex_byte(const string& s) { 223 istringstream in(s); 224 int result = 0; 225 in >> std::hex >> result; -226 if (!in) { -227 raise << "invalid hex " << s << '\n' << end(); +226 if (!in || !in.eof()) { +227 raise << "token '" << s << "' is not a hex byte\n" << end(); 228 return '\0'; 229 } -230 if (result > 0xff) { -231 raise << "invalid hex byte " << std::hex << result << '\n' << end(); +230 if (result > 0xff || result < -0x8f) { +231 raise << "token '" << s << "' is not a hex byte\n" << end(); 232 return '\0'; 233 } 234 return static_cast<uint8_t>(result); 235 } 236 -237 //:: run -238 -239 :(before "End Initialize Op Names(name)") -240 put(name, "05", "add imm32 to R0 (EAX)"); -241 -242 //: our first opcode -243 :(before "End Single-Byte Opcodes") -244 case 0x05: { // add imm32 to EAX -245 int32_t arg2 = imm32(); -246 trace(90, "run") << "add imm32 0x" << HEXWORD << arg2 << " to reg EAX" << end(); -247 BINARY_ARITHMETIC_OP(+, Reg[EAX].i, arg2); -248 break; -249 } -250 -251 :(code) -252 // read a 32-bit immediate in little-endian order from the instruction stream -253 int32_t imm32() { -254 int32_t result = next(); -255 result |= (next()<<8); -256 result |= (next()<<16); -257 result |= (next()<<24); -258 return result; -259 } +237 :(scenarios parse_and_load) +238 :(scenario number_too_large) +239 % Hide_errors = true; +240 == 0x1 +241 05 cab +242 +error: token 'cab' is not a hex byte +243 +244 :(scenario invalid_hex) +245 % Hide_errors = true; +246 == 0x1 +247 05 cx +248 +error: token 'cx' is not a hex byte +249 +250 :(scenario negative_number) +251 == 0x1 +252 05 -12 +253 $error: 0 +254 +255 :(scenario negative_number_too_small) +256 % Hide_errors = true; +257 == 0x1 +258 05 -12345 +259 +error: token '-12345' is not a hex byte +260 +261 :(scenario hex_prefix) +262 == 0x1 +263 0x05 -0x12 +264 $error: 0 +265 +266 //: helper for tests +267 :(code) +268 void parse_and_load(const string& text_bytes) { +269 program p; +270 istringstream in(text_bytes); +271 parse(in, p); +272 if (trace_contains_errors()) return; // if any stage raises errors, stop immediately +273 load(p); +274 } +275 +276 //:: run +277 +278 :(before "End Initialize Op Names(name)") +279 put(name, "05", "add imm32 to R0 (EAX)"); +280 +281 //: our first opcode +282 :(before "End Single-Byte Opcodes") +283 case 0x05: { // add imm32 to EAX +284 int32_t arg2 = imm32(); +285 trace(90, "run") << "add imm32 0x" << HEXWORD << arg2 << " to reg EAX" << end(); +286 BINARY_ARITHMETIC_OP(+, Reg[EAX].i, arg2); +287 break; +288 } +289 +290 :(code) +291 // read a 32-bit immediate in little-endian order from the instruction stream +292 int32_t imm32() { +293 int32_t result = next(); +294 result |= (next()<<8); +295 result |= (next()<<16); +296 result |= (next()<<24); +297 return result; +298 } -- cgit 1.4.1-2-gfad0