about summary refs log tree commit diff stats
path: root/subx/021byte_addressing.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-03-12 18:56:55 -0700
committerKartik Agaram <vc@akkartik.com>2019-03-12 19:14:12 -0700
commit4a943d4ed313eff001504c2b5c472266e86a38af (patch)
treea5757233a8c81b303a808f251180c7344071ed51 /subx/021byte_addressing.cc
parent43711b0e9f18e0225ce14687fb6ea0902aa6fc61 (diff)
downloadmu-4a943d4ed313eff001504c2b5c472266e86a38af.tar.gz
5001 - drop the :(scenario) DSL
I've been saying for a while[1][2][3] that adding extra abstractions makes
things harder for newcomers, and adding new notations doubly so. And then
I notice this DSL in my own backyard. Makes me feel like a hypocrite.

[1] https://news.ycombinator.com/item?id=13565743#13570092
[2] https://lobste.rs/s/to8wpr/configuration_files_are_canary_warning
[3] https://lobste.rs/s/mdmcdi/little_languages_by_jon_bentley_1986#c_3miuf2

The implementation of the DSL was also highly hacky:

a) It was happening in the tangle/ tool, but was utterly unrelated to tangling
layers.

b) There were several persnickety constraints on the different kinds of
lines and the specific order they were expected in. I kept finding bugs
where the translator would silently do the wrong thing. Or the error messages
sucked, and readers may be stuck looking at the generated code to figure
out what happened. Fixing error messages would require a lot more code,
which is one of my arguments against DSLs in the first place: they may
be easy to implement, but they're hard to design to go with the grain of
the underlying platform. They require lots of iteration. Is that effort
worth prioritizing in this project?

On the other hand, the DSL did make at least some readers' life easier,
the ones who weren't immediately put off by having to learn a strange syntax.
There were fewer quotes to parse, fewer backslash escapes.

Anyway, since there are also people who dislike having to put up with strange
syntaxes, we'll call that consideration a wash and tear this DSL out.

---

This commit was sheer drudgery. Hopefully it won't need to be redone with
a new DSL because I grow sick of backslashes.
Diffstat (limited to 'subx/021byte_addressing.cc')
-rw-r--r--subx/021byte_addressing.cc126
1 files changed, 75 insertions, 51 deletions
diff --git a/subx/021byte_addressing.cc b/subx/021byte_addressing.cc
index c96bc9c1..106cd426 100644
--- a/subx/021byte_addressing.cc
+++ b/subx/021byte_addressing.cc
@@ -40,19 +40,25 @@ uint8_t* reg_8bit(uint8_t rm) {
 :(before "End Initialize Op Names")
 put_new(Name, "88", "copy r8 to r8/m8-at-r32");
 
-:(scenario copy_r8_to_mem_at_r32)
-% Reg[EBX].i = 0x224488ab;
-% Reg[EAX].i = 0x2000;
-== 0x1
-# op  ModR/M  SIB   displacement  immediate
-  88  18                                      # copy BL to the byte at *EAX
-# ModR/M in binary: 00 (indirect mode) 011 (src BL) 000 (dest EAX)
-== 0x2000
-f0 cc bb aa
-+run: copy BL to r8/m8-at-r32
-+run: effective address is 0x00002000 (EAX)
-+run: storing 0xab
-% CHECK_EQ(0xaabbccab, read_mem_u32(0x2000));
+:(code)
+void test_copy_r8_to_mem_at_r32() {
+  Reg[EBX].i = 0x224488ab;
+  Reg[EAX].i = 0x2000;
+  run(
+      "== 0x1\n"  // code segment
+      // op     ModR/M  SIB   displacement  immediate
+      "  88     18                                      \n"  // copy BL to the byte at *EAX
+      // ModR/M in binary: 00 (indirect mode) 011 (src BL) 000 (dest EAX)
+      "== 0x2000\n"  // data segment
+      "f0 cc bb aa\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "run: copy BL to r8/m8-at-r32\n"
+      "run: effective address is 0x00002000 (EAX)\n"
+      "run: storing 0xab\n"
+  );
+  CHECK_EQ(0xaabbccab, read_mem_u32(0x2000));
+}
 
 :(before "End Single-Byte Opcodes")
 case 0x88: {  // copy r8 to r/m8
@@ -72,20 +78,26 @@ case 0x88: {  // copy r8 to r/m8
 :(before "End Initialize Op Names")
 put_new(Name, "8a", "copy r8/m8-at-r32 to r8");
 
-:(scenario copy_mem_at_r32_to_r8)
-% Reg[EBX].i = 0xaabbcc0f;  // one nibble each of lowest byte set to all 0s and all 1s, to maximize value of this test
-% Reg[EAX].i = 0x2000;
-== 0x1
-# op  ModR/M  SIB   displacement  immediate
-  8a  18                                      # copy just the byte at *EAX to BL
-# ModR/M in binary: 00 (indirect mode) 011 (dest EBX) 000 (src EAX)
-== 0x2000  # data segment
-ab ff ff ff  # 0xab with more data in following bytes
-+run: copy r8/m8-at-r32 to BL
-+run: effective address is 0x00002000 (EAX)
-+run: storing 0xab
-# remaining bytes of EBX are *not* cleared
-+run: EBX now contains 0xaabbccab
+:(code)
+void test_copy_mem_at_r32_to_r8() {
+  Reg[EBX].i = 0xaabbcc0f;  // one nibble each of lowest byte set to all 0s and all 1s, to maximize value of this test
+  Reg[EAX].i = 0x2000;
+  run(
+      "== 0x1\n"  // code segment
+      // op     ModR/M  SIB   displacement  immediate
+      "  8a     18                                      \n"  // copy just the byte at *EAX to BL
+      // ModR/M in binary: 00 (indirect mode) 011 (dest EBX) 000 (src EAX)
+      "== 0x2000\n"  // data segment
+      "ab ff ff ff\n"  // 0xab with more data in following bytes
+  );
+  CHECK_TRACE_CONTENTS(
+      "run: copy r8/m8-at-r32 to BL\n"
+      "run: effective address is 0x00002000 (EAX)\n"
+      "run: storing 0xab\n"
+      // remaining bytes of EBX are *not* cleared
+      "run: EBX now contains 0xaabbccab\n"
+  );
+}
 
 :(before "End Single-Byte Opcodes")
 case 0x8a: {  // copy r/m8 to r8
@@ -102,36 +114,48 @@ case 0x8a: {  // copy r/m8 to r8
   break;
 }
 
-:(scenario cannot_copy_byte_to_ESP_EBP_ESI_EDI)
-% Reg[ESI].u = 0xaabbccdd;
-% Reg[EBX].u = 0x11223344;
-== 0x1
-# op  ModR/M  SIB   displacement  immediate
-  8a  f3                                      # copy just the byte at *EBX to 8-bit register '6'
-# ModR/M in binary: 11 (direct mode) 110 (dest 8-bit 'register 6') 011 (src EBX)
-# ensure 8-bit register '6' is DH, not ESI
-+run: copy r8/m8-at-r32 to DH
-+run: storing 0x44
-# ensure ESI is unchanged
-% CHECK_EQ(Reg[ESI].u, 0xaabbccdd);
+:(code)
+void test_cannot_copy_byte_to_ESP_EBP_ESI_EDI() {
+  Reg[ESI].u = 0xaabbccdd;
+  Reg[EBX].u = 0x11223344;
+  run(
+      "== 0x1\n"  // code segment
+      // op     ModR/M  SIB   displacement  immediate
+      "  8a     f3                                      \n"  // copy just the byte at *EBX to 8-bit register '6'
+      // ModR/M in binary: 11 (direct mode) 110 (dest 8-bit 'register 6') 011 (src EBX)
+  );
+  CHECK_TRACE_CONTENTS(
+      // ensure 8-bit register '6' is DH, not ESI
+      "run: copy r8/m8-at-r32 to DH\n"
+      "run: storing 0x44\n"
+  );
+  // ensure ESI is unchanged
+  CHECK_EQ(Reg[ESI].u, 0xaabbccdd);
+}
 
 //:
 
 :(before "End Initialize Op Names")
 put_new(Name, "c6", "copy imm8 to r8/m8-at-r32 (mov)");
 
-:(scenario copy_imm8_to_mem_at_r32)
-% Reg[EAX].i = 0x2000;
-== 0x1
-# op  ModR/M  SIB   displacement  immediate
-  c6  00                          dd          # copy to the byte at *EAX
-# ModR/M in binary: 00 (indirect mode) 000 (unused) 000 (dest EAX)
-== 0x2000
-f0 cc bb aa
-+run: copy imm8 to r8/m8-at-r32
-+run: effective address is 0x00002000 (EAX)
-+run: storing 0xdd
-% CHECK_EQ(0xaabbccdd, read_mem_u32(0x2000));
+:(code)
+void test_copy_imm8_to_mem_at_r32() {
+  Reg[EAX].i = 0x2000;
+  run(
+      "== 0x1\n"  // code segment
+      // op     ModR/M  SIB   displacement  immediate
+      "  c6     00                          dd          \n"  // copy to the byte at *EAX
+      // ModR/M in binary: 00 (indirect mode) 000 (unused) 000 (dest EAX)
+      "== 0x2000\n"  // data segment
+      "f0 cc bb aa\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "run: copy imm8 to r8/m8-at-r32\n"
+      "run: effective address is 0x00002000 (EAX)\n"
+      "run: storing 0xdd\n"
+  );
+  CHECK_EQ(0xaabbccdd, read_mem_u32(0x2000));
+}
 
 :(before "End Single-Byte Opcodes")
 case 0xc6: {  // copy imm8 to r/m8