summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild/sim86bin65872 -> 61656 bytes
-rwxr-xr-xbuild/sim86_metabin181968 -> 177464 bytes
-rw-r--r--computerenhance.md7
-rw-r--r--data/estimating_cycles/listing_0056_estimating_cyclesbin0 -> 55 bytes
-rw-r--r--data/estimating_cycles/listing_0056_estimating_cycles.asm41
-rw-r--r--data/estimating_cycles/listing_0056_estimating_cycles.txt72
-rw-r--r--data/estimating_cycles/listing_0057_challenge_cycles2
-rw-r--r--data/estimating_cycles/listing_0057_challenge_cycles.asm42
-rw-r--r--data/estimating_cycles/listing_0057_challenge_cycles.txt71
-rw-r--r--project.4coder1
-rwxr-xr-xsrc/build.sh7
-rw-r--r--src/clocks_table.inl51
-rw-r--r--src/generated/generated.cpp13
-rw-r--r--src/sim86.cpp153
-rw-r--r--src/sim86.h23
-rw-r--r--src/sim86.mdesk22
-rw-r--r--src/sim86_meta.c7
17 files changed, 443 insertions, 69 deletions
diff --git a/build/sim86 b/build/sim86
index 4e86ddf..08e2c7c 100755
--- a/build/sim86
+++ b/build/sim86
Binary files differ
diff --git a/build/sim86_meta b/build/sim86_meta
index 8226ed8..c7b2e28 100755
--- a/build/sim86_meta
+++ b/build/sim86_meta
Binary files differ
diff --git a/computerenhance.md b/computerenhance.md
index 3df3bda..1733704 100644
--- a/computerenhance.md
+++ b/computerenhance.md
@@ -732,11 +732,16 @@ Calling conventions and ABIs are rules so code can operate with other code when
You can spot memory access by brackets '[]'.
Either a load/store or LEA or prefetch. LEA does a load with a temp registers.
You can use the stack as regular memory by saving `sp` (stack pointer) to a register and offsetting from it.
-A stack frame is a context view of a "call".
+A stack frame is the part of the stack created by a function.
# 36. [Performance Excuses Debunked](https://www.computerenhance.com/p/performance-excuses-debunked)
# 37. [Estimating Cycles](https://www.computerenhance.com/p/estimating-cycles)
+By using estimation you can know what your performance *should* be.
+clocks=cycles
+
# 38. [Monday Q&A #10 (2023-05-08)](https://www.computerenhance.com/p/monday-q-and-a-10-2023-05-08)
+With SIMD using smaller numbers will be faster.
+
# 39. [From 8086 to x64](https://www.computerenhance.com/p/from-8086-to-x64)
# 40. [8086 Internals Poll](https://www.computerenhance.com/p/8086-internals-poll)
# 41. [How to Play Trinity](https://www.computerenhance.com/p/how-to-play-trinity)
diff --git a/data/estimating_cycles/listing_0056_estimating_cycles b/data/estimating_cycles/listing_0056_estimating_cycles
new file mode 100644
index 0000000..bb15fc7
--- /dev/null
+++ b/data/estimating_cycles/listing_0056_estimating_cycles
Binary files differ
diff --git a/data/estimating_cycles/listing_0056_estimating_cycles.asm b/data/estimating_cycles/listing_0056_estimating_cycles.asm
new file mode 100644
index 0000000..3a28ddd
--- /dev/null
+++ b/data/estimating_cycles/listing_0056_estimating_cycles.asm
@@ -0,0 +1,41 @@
+; ========================================================================
+;
+; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
+;
+; This software is provided 'as-is', without any express or implied
+; warranty. In no event will the authors be held liable for any damages
+; arising from the use of this software.
+;
+; Please see https://computerenhance.com for further information
+;
+; ========================================================================
+
+; ========================================================================
+; LISTING 56
+; ========================================================================
+
+bits 16
+
+mov bx, 1000
+mov bp, 2000
+mov si, 3000
+mov di, 4000
+
+mov cx, bx
+mov dx, 12
+
+mov dx, [1000]
+
+mov cx, [bx]
+mov cx, [bp]
+mov [si], cx
+mov [di], cx
+
+mov cx, [bx + 1000]
+mov cx, [bp + 1000]
+mov [si + 1000], cx
+mov [di + 1000], cx
+
+add cx, dx
+add [di + 1000], cx
+add dx, 50
diff --git a/data/estimating_cycles/listing_0056_estimating_cycles.txt b/data/estimating_cycles/listing_0056_estimating_cycles.txt
new file mode 100644
index 0000000..6997cec
--- /dev/null
+++ b/data/estimating_cycles/listing_0056_estimating_cycles.txt
@@ -0,0 +1,72 @@
+**************
+**** 8086 ****
+**************
+
+WARNING: Clocks reported by this utility are strictly from the 8086 manual.
+They will be inaccurate, both because the manual clocks are estimates, and because
+some of the entries in the manual look highly suspicious and are probably typos.
+
+--- test\listing_0056_estimating_cycles execution ---
+mov bx, 1000 ; Clocks: +4 = 4 | bx:0x0->0x3e8 ip:0x0->0x3
+mov bp, 2000 ; Clocks: +4 = 8 | bp:0x0->0x7d0 ip:0x3->0x6
+mov si, 3000 ; Clocks: +4 = 12 | si:0x0->0xbb8 ip:0x6->0x9
+mov di, 4000 ; Clocks: +4 = 16 | di:0x0->0xfa0 ip:0x9->0xc
+mov cx, bx ; Clocks: +2 = 18 | cx:0x0->0x3e8 ip:0xc->0xe
+mov dx, 12 ; Clocks: +4 = 22 | dx:0x0->0xc ip:0xe->0x11
+mov dx, [+1000] ; Clocks: +14 = 36 (8 + 6ea) | dx:0xc->0x0 ip:0x11->0x15
+mov cx, [bx] ; Clocks: +13 = 49 (8 + 5ea) | cx:0x3e8->0x0 ip:0x15->0x17
+mov cx, [bp] ; Clocks: +13 = 62 (8 + 5ea) | ip:0x17->0x1a
+mov word [si], cx ; Clocks: +14 = 76 (9 + 5ea) | ip:0x1a->0x1c
+mov word [di], cx ; Clocks: +14 = 90 (9 + 5ea) | ip:0x1c->0x1e
+mov cx, [bx+1000] ; Clocks: +17 = 107 (8 + 9ea) | ip:0x1e->0x22
+mov cx, [bp+1000] ; Clocks: +17 = 124 (8 + 9ea) | ip:0x22->0x26
+mov word [si+1000], cx ; Clocks: +18 = 142 (9 + 9ea) | ip:0x26->0x2a
+mov word [di+1000], cx ; Clocks: +18 = 160 (9 + 9ea) | ip:0x2a->0x2e
+add cx, dx ; Clocks: +3 = 163 | ip:0x2e->0x30 flags:->PZ
+add word [di+1000], cx ; Clocks: +25 = 188 (16 + 9ea) | ip:0x30->0x34
+add dx, 50 ; Clocks: +4 = 192 | dx:0x0->0x32 ip:0x34->0x37 flags:PZ->
+
+Final registers:
+ bx: 0x03e8 (1000)
+ dx: 0x0032 (50)
+ bp: 0x07d0 (2000)
+ si: 0x0bb8 (3000)
+ di: 0x0fa0 (4000)
+ ip: 0x0037 (55)
+
+
+**************
+**** 8088 ****
+**************
+
+WARNING: Clocks reported by this utility are strictly from the 8086 manual.
+They will be inaccurate, both because the manual clocks are estimates, and because
+some of the entries in the manual look highly suspicious and are probably typos.
+
+--- test\listing_0056_estimating_cycles execution ---
+mov bx, 1000 ; Clocks: +4 = 4 | bx:0x0->0x3e8 ip:0x0->0x3
+mov bp, 2000 ; Clocks: +4 = 8 | bp:0x0->0x7d0 ip:0x3->0x6
+mov si, 3000 ; Clocks: +4 = 12 | si:0x0->0xbb8 ip:0x6->0x9
+mov di, 4000 ; Clocks: +4 = 16 | di:0x0->0xfa0 ip:0x9->0xc
+mov cx, bx ; Clocks: +2 = 18 | cx:0x0->0x3e8 ip:0xc->0xe
+mov dx, 12 ; Clocks: +4 = 22 | dx:0x0->0xc ip:0xe->0x11
+mov dx, [+1000] ; Clocks: +18 = 40 (8 + 6ea + 4p) | dx:0xc->0x0 ip:0x11->0x15
+mov cx, [bx] ; Clocks: +17 = 57 (8 + 5ea + 4p) | cx:0x3e8->0x0 ip:0x15->0x17
+mov cx, [bp] ; Clocks: +17 = 74 (8 + 5ea + 4p) | ip:0x17->0x1a
+mov word [si], cx ; Clocks: +18 = 92 (9 + 5ea + 4p) | ip:0x1a->0x1c
+mov word [di], cx ; Clocks: +18 = 110 (9 + 5ea + 4p) | ip:0x1c->0x1e
+mov cx, [bx+1000] ; Clocks: +21 = 131 (8 + 9ea + 4p) | ip:0x1e->0x22
+mov cx, [bp+1000] ; Clocks: +21 = 152 (8 + 9ea + 4p) | ip:0x22->0x26
+mov word [si+1000], cx ; Clocks: +22 = 174 (9 + 9ea + 4p) | ip:0x26->0x2a
+mov word [di+1000], cx ; Clocks: +22 = 196 (9 + 9ea + 4p) | ip:0x2a->0x2e
+add cx, dx ; Clocks: +3 = 199 | ip:0x2e->0x30 flags:->PZ
+add word [di+1000], cx ; Clocks: +33 = 232 (16 + 9ea + 8p) | ip:0x30->0x34
+add dx, 50 ; Clocks: +4 = 236 | dx:0x0->0x32 ip:0x34->0x37 flags:PZ->
+
+Final registers:
+ bx: 0x03e8 (1000)
+ dx: 0x0032 (50)
+ bp: 0x07d0 (2000)
+ si: 0x0bb8 (3000)
+ di: 0x0fa0 (4000)
+ ip: 0x0037 (55)
diff --git a/data/estimating_cycles/listing_0057_challenge_cycles b/data/estimating_cycles/listing_0057_challenge_cycles
new file mode 100644
index 0000000..59b206e
--- /dev/null
+++ b/data/estimating_cycles/listing_0057_challenge_cycles
@@ -0,0 +1,2 @@
+»è½Ð¾¸ ¿ ‹ ‰‹
+‰ ‹‹è‰ˆè‹Šè‰‰è’èƒL’é•çƒK \ No newline at end of file
diff --git a/data/estimating_cycles/listing_0057_challenge_cycles.asm b/data/estimating_cycles/listing_0057_challenge_cycles.asm
new file mode 100644
index 0000000..4a9adb0
--- /dev/null
+++ b/data/estimating_cycles/listing_0057_challenge_cycles.asm
@@ -0,0 +1,42 @@
+; ========================================================================
+;
+; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
+;
+; This software is provided 'as-is', without any express or implied
+; warranty. In no event will the authors be held liable for any damages
+; arising from the use of this software.
+;
+; Please see https://computerenhance.com for further information
+;
+; ========================================================================
+
+; ========================================================================
+; LISTING 57
+; ========================================================================
+
+bits 16
+
+mov bx, 1000
+mov bp, 2000
+mov si, 3000
+mov di, 4000
+
+mov cx, [bp + di]
+mov [bx + si], cx
+
+mov cx, [bp + si]
+mov [bx + di], cx
+
+mov cx, [bp + di + 1000]
+mov [bx + si + 1000], cx
+
+mov cx, [bp + si + 1000]
+mov [bx + di + 1000], cx
+
+add dx, [bp + si + 1000]
+
+add word [bp + si], 76
+
+add dx, [bp + si + 1001]
+add [di + 999], dx
+add word [bp + si], 75
diff --git a/data/estimating_cycles/listing_0057_challenge_cycles.txt b/data/estimating_cycles/listing_0057_challenge_cycles.txt
new file mode 100644
index 0000000..51cceb4
--- /dev/null
+++ b/data/estimating_cycles/listing_0057_challenge_cycles.txt
@@ -0,0 +1,71 @@
+**************
+**** 8086 ****
+**************
+
+WARNING: Clocks reported by this utility are strictly from the 8086 manual.
+They will be inaccurate, both because the manual clocks are estimates, and because
+some of the entries in the manual look highly suspicious and are probably typos.
+
+--- test\listing_0057_challenge_cycles execution ---
+mov bx, 1000 ; Clocks: +4 = 4 | bx:0x0->0x3e8 ip:0x0->0x3
+mov bp, 2000 ; Clocks: +4 = 8 | bp:0x0->0x7d0 ip:0x3->0x6
+mov si, 3000 ; Clocks: +4 = 12 | si:0x0->0xbb8 ip:0x6->0x9
+mov di, 4000 ; Clocks: +4 = 16 | di:0x0->0xfa0 ip:0x9->0xc
+mov cx, [bp+di] ; Clocks: +15 = 31 (8 + 7ea) | ip:0xc->0xe
+mov word [bx+si], cx ; Clocks: +16 = 47 (9 + 7ea) | ip:0xe->0x10
+mov cx, [bp+si] ; Clocks: +16 = 63 (8 + 8ea) | ip:0x10->0x12
+mov word [bx+di], cx ; Clocks: +17 = 80 (9 + 8ea) | ip:0x12->0x14
+mov cx, [bp+di+1000] ; Clocks: +19 = 99 (8 + 11ea) | ip:0x14->0x18
+mov word [bx+si+1000], cx ; Clocks: +20 = 119 (9 + 11ea) | ip:0x18->0x1c
+mov cx, [bp+si+1000] ; Clocks: +20 = 139 (8 + 12ea) | ip:0x1c->0x20
+mov word [bx+di+1000], cx ; Clocks: +21 = 160 (9 + 12ea) | ip:0x20->0x24
+add dx, [bp+si+1000] ; Clocks: +21 = 181 (9 + 12ea) | ip:0x24->0x28 flags:->PZ
+add word [bp+si], 76 ; Clocks: +25 = 206 (17 + 8ea) | ip:0x28->0x2b flags:PZ->
+add dx, [bp+si+1001] ; Clocks: +25 = 231 (9 + 12ea + 4p) | ip:0x2b->0x2f flags:->PZ
+add word [di+999], dx ; Clocks: +33 = 264 (16 + 9ea + 8p) | ip:0x2f->0x33 flags:PZ->P
+add word [bp+si], 75 ; Clocks: +25 = 289 (17 + 8ea) | ip:0x33->0x36 flags:P->A
+
+Final registers:
+ bx: 0x03e8 (1000)
+ bp: 0x07d0 (2000)
+ si: 0x0bb8 (3000)
+ di: 0x0fa0 (4000)
+ ip: 0x0036 (54)
+ flags: A
+
+
+
+**************
+**** 8088 ****
+**************
+
+WARNING: Clocks reported by this utility are strictly from the 8086 manual.
+They will be inaccurate, both because the manual clocks are estimates, and because
+some of the entries in the manual look highly suspicious and are probably typos.
+
+--- test\listing_0057_challenge_cycles execution ---
+mov bx, 1000 ; Clocks: +4 = 4 | bx:0x0->0x3e8 ip:0x0->0x3
+mov bp, 2000 ; Clocks: +4 = 8 | bp:0x0->0x7d0 ip:0x3->0x6
+mov si, 3000 ; Clocks: +4 = 12 | si:0x0->0xbb8 ip:0x6->0x9
+mov di, 4000 ; Clocks: +4 = 16 | di:0x0->0xfa0 ip:0x9->0xc
+mov cx, [bp+di] ; Clocks: +19 = 35 (8 + 7ea + 4p) | ip:0xc->0xe
+mov word [bx+si], cx ; Clocks: +20 = 55 (9 + 7ea + 4p) | ip:0xe->0x10
+mov cx, [bp+si] ; Clocks: +20 = 75 (8 + 8ea + 4p) | ip:0x10->0x12
+mov word [bx+di], cx ; Clocks: +21 = 96 (9 + 8ea + 4p) | ip:0x12->0x14
+mov cx, [bp+di+1000] ; Clocks: +23 = 119 (8 + 11ea + 4p) | ip:0x14->0x18
+mov word [bx+si+1000], cx ; Clocks: +24 = 143 (9 + 11ea + 4p) | ip:0x18->0x1c
+mov cx, [bp+si+1000] ; Clocks: +24 = 167 (8 + 12ea + 4p) | ip:0x1c->0x20
+mov word [bx+di+1000], cx ; Clocks: +25 = 192 (9 + 12ea + 4p) | ip:0x20->0x24
+add dx, [bp+si+1000] ; Clocks: +25 = 217 (9 + 12ea + 4p) | ip:0x24->0x28 flags:->PZ
+add word [bp+si], 76 ; Clocks: +33 = 250 (17 + 8ea + 8p) | ip:0x28->0x2b flags:PZ->
+add dx, [bp+si+1001] ; Clocks: +25 = 275 (9 + 12ea + 4p) | ip:0x2b->0x2f flags:->PZ
+add word [di+999], dx ; Clocks: +33 = 308 (16 + 9ea + 8p) | ip:0x2f->0x33 flags:PZ->P
+add word [bp+si], 75 ; Clocks: +33 = 341 (17 + 8ea + 8p) | ip:0x33->0x36 flags:P->A
+
+Final registers:
+ bx: 0x03e8 (1000)
+ bp: 0x07d0 (2000)
+ si: 0x0bb8 (3000)
+ di: 0x0fa0 (4000)
+ ip: 0x0036 (54)
+ flags: A
diff --git a/project.4coder b/project.4coder
index c06e98e..24c2c82 100644
--- a/project.4coder
+++ b/project.4coder
@@ -2,6 +2,7 @@ version(2);
project_name = "sim8086";
patterns = {
"*.c",
+ "*.mdesk",
"*.cpp",
"*.h",
"*.m",
diff --git a/src/build.sh b/src/build.sh
index 8cfb982..7726aee 100755
--- a/src/build.sh
+++ b/src/build.sh
@@ -28,17 +28,14 @@ WarningFlags="
-Wno-write-strings
"
-Libs="./libs/reference_decoder/sim86_lib.cpp"
-
printf '[metadata generation]\n'
-Source="sim86_meta.c"
$Compiler $CompilerFlags $WarningFlags \
-o ../build/sim86_meta \
- $Source
+ sim86_meta.c
../build/sim86_meta ./sim86.mdesk > ./generated/generated.cpp
printf '[%s build]\n' "$Compiler"
Source="sim86.cpp"
$Compiler $CompilerFlags $WarningFlags \
-o ../build/sim86 \
- $Libs $Source
+ sim86.cpp
diff --git a/src/clocks_table.inl b/src/clocks_table.inl
new file mode 100644
index 0000000..2c07bb3
--- /dev/null
+++ b/src/clocks_table.inl
@@ -0,0 +1,51 @@
+
+enum instruction_clocks_operand_type
+{
+ InstructionClocksOperand_None = 0,
+ InstructionClocksOperand_Memory,
+ InstructionClocksOperand_Immediate,
+ InstructionClocksOperand_Accumulator,
+ InstructionClocksOperand_Register,
+ InstructionClocksOperand_Count
+};
+
+struct instruction_clocks
+{
+ operation_type Op;
+ instruction_clocks_operand_type Operands[2];
+ u32 Clocks;
+ u32 Transfers;
+ b32 EffectiveAddress;
+};
+
+#define Memory InstructionClocksOperand_Memory
+#define Immediate InstructionClocksOperand_Immediate
+#define Accumulator InstructionClocksOperand_Accumulator
+#define Register InstructionClocksOperand_Register
+#define None InstructionClocksOperand_None
+
+// NOTE(luca): Instructions containing accumulator should be put first so they have precedence
+// on instructions with registers (accumulator is a register).
+instruction_clocks ClocksTable[] =
+{
+ { Op_mov, { Memory, Accumulator }, 10, 1, false },
+ { Op_mov, { Accumulator, Memory }, 10, 1, false },
+ { Op_mov, { Register, Register }, 2, 0, false },
+ { Op_mov, { Register, Memory }, 8, 1, true },
+ { Op_mov, { Memory, Register }, 9, 1, true },
+ { Op_mov, { Register, Immediate }, 4, 0, false },
+ { Op_mov, { Memory, Immediate }, 10, 1, true },
+
+ { Op_add, { Accumulator, Immediate }, 4, 0, false },
+ { Op_add, { Register, Register }, 3, 0, false },
+ { Op_add, { Register, Memory }, 9, 1, true },
+ { Op_add, { Memory, Register }, 16, 2, true },
+ { Op_add, { Register, Immediate }, 4, 0, false },
+ { Op_add, { Memory, Immediate }, 17, 2, true },
+};
+
+#undef Memory
+#undef Register
+#undef None
+#undef Accumulator
+#undef Immediate \ No newline at end of file
diff --git a/src/generated/generated.cpp b/src/generated/generated.cpp
index 1ad803c..0f457a1 100644
--- a/src/generated/generated.cpp
+++ b/src/generated/generated.cpp
@@ -1,16 +1,3 @@
-enum flags_songs
-{
- Flag_French = (1 << 0),
- Flag_Russian = (1 << 1),
-};
-
-int songs_strings_count = 2;
-char *songs_strings[] =
-{
- "French Blues",
- "Russian Blues",
-};
-
enum flags_8086
{
Flag_Carry = (1 << 0),
diff --git a/src/sim86.cpp b/src/sim86.cpp
index ba9e252..e5480d7 100644
--- a/src/sim86.cpp
+++ b/src/sim86.cpp
@@ -1,9 +1,10 @@
#include <stdio.h>
#include <string.h>
-#include "sim86.h"
-#include "sim86_shared.h"
+#include "./libs/reference_decoder/sim86_lib.cpp"
+#include "sim86.h"
+#include "clocks_table.inl"
#include "generated/generated.cpp"
global_variable u8 GlobalMemory[1*1024*1024] = {};
@@ -82,6 +83,19 @@ FlagsFromValue(u32 *FlagsRegister, u32 InstructionFlags, s32 Value)
}
}
+s32 GetCompleteDisplacement(s32 *Registers, instruction_operand *Operand)
+{
+ s32 CompleteDisplacement = Operand->Address.Displacement;
+
+ u32 Count = Operand->Address.Terms[0].Register.Count;
+ u32 Mask = ((u32)((-1)) >> (16 + (16 - Count*8)));
+ CompleteDisplacement +=
+ (Registers[Operand->Address.Terms[0].Register.Index] & Mask) +
+ (Registers[Operand->Address.Terms[1].Register.Index] & Mask);
+
+ return CompleteDisplacement;
+}
+
internal s32 *
OperandToValue(s32 *Registers, u8 *Memory, instruction_operand *Operand)
{
@@ -94,16 +108,7 @@ OperandToValue(s32 *Registers, u8 *Memory, instruction_operand *Operand)
}
else if(Operand->Type == Operand_Memory)
{
- s32 CompleteDisplacement = Operand->Address.Displacement;
- Assert(Operand->Address.Terms[0].Register.Count == Operand->Address.Terms[1].Register.Count);
-
- u32 Count = Operand->Address.Terms[0].Register.Count;
- u32 Mask = ((u32)((-1)) >> (16 + (16 - Count*8)));
-
- CompleteDisplacement +=
- (Registers[Operand->Address.Terms[0].Register.Index] & Mask) +
- (Registers[Operand->Address.Terms[1].Register.Index] & Mask);
-
+ s32 CompleteDisplacement = GetCompleteDisplacement(Registers, Operand);
Result = (s32 *)((u8 *)Memory + CompleteDisplacement);
}
else if(Operand->Type == Operand_Immediate)
@@ -118,12 +123,32 @@ OperandToValue(s32 *Registers, u8 *Memory, instruction_operand *Operand)
return Result;
}
+b32 IsAccumulator(instruction_operand *Operand)
+{
+ b32 Result = ((Operand->Type == Operand_Register) &&
+ (Operand->Register.Index == Register_a));
+ return Result;
+}
+
+b32 IsMatchingOp(instruction_operand *Operand, instruction_clocks_operand_type Type)
+{
+ b32 Matching = false;
+
+ Matching = Matching || (Type == InstructionClocksOperand_Memory && Operand->Type == Operand_Memory);
+ Matching = Matching || (Type == InstructionClocksOperand_Register && Operand->Type == Operand_Register);
+ Matching = Matching || (Type == InstructionClocksOperand_Accumulator && IsAccumulator(Operand));
+ Matching = Matching || (Type == InstructionClocksOperand_Immediate && Operand->Type == Operand_Immediate);
+
+ return Matching;
+}
+
internal void
Run8086(psize MemorySize, u8 *Memory)
{
s32 Registers[Register_count] = {};
u32 FlagsRegister = 0;
u32 IPRegister = 0;
+ u32 ElapsedClocks = 0;
while(IPRegister < MemorySize)
{
@@ -135,12 +160,110 @@ Run8086(psize MemorySize, u8 *Memory)
IPRegister += Decoded.Size;
#if SIM86_INTERNAL
- printf("Size:%u Op:%s Flags:0x%x ;", Decoded.Size, Sim86_MnemonicFromOperationType(Decoded.Op), Decoded.Flags);
+ printf("%s ;", Sim86_MnemonicFromOperationType(Decoded.Op));
#endif
instruction_operand *DestinationOperand = Decoded.Operands + 0;
instruction_operand *SourceOperand = Decoded.Operands + 1;
+ u32 AddedClocks = 0;
+ for(u32 ClocksIndex = 0;
+ ClocksIndex < ArrayCount(ClocksTable);
+ ClocksIndex++)
+ {
+ instruction_clocks *Clocks = ClocksTable + ClocksIndex;
+
+ b32 Matching = Decoded.Op == Clocks->Op;
+ Matching = Matching && IsMatchingOp(DestinationOperand, Clocks->Operands[0]);
+ Matching = Matching && IsMatchingOp(SourceOperand, Clocks->Operands[1]);
+ if(Matching)
+ {
+ AddedClocks += Clocks->Clocks;
+
+ if(Clocks->EffectiveAddress)
+ {
+ instruction_operand *MemoryOperand = ((DestinationOperand->Type == Operand_Memory) ? DestinationOperand : SourceOperand);
+ u32 FirstIndex = MemoryOperand->Address.Terms[0].Register.Index;
+ u32 SecondIndex = MemoryOperand->Address.Terms[1].Register.Index;
+
+ // Only displacement
+ if(FirstIndex == 0 && SecondIndex == 0)
+ {
+ AddedClocks += 6;
+ }
+ // Base or index
+ else if(FirstIndex == 0 || SecondIndex == 0)
+ {
+ // Base or index only
+ if(MemoryOperand->Address.Displacement == 0)
+ {
+ AddedClocks += 5;
+ }
+ // Base or index + displacement
+ else
+ {
+ AddedClocks += 9;
+ }
+ }
+ // Base + index
+ else if(MemoryOperand->Address.Displacement == 0)
+ {
+ /*
+ bp+di bx+si 7
+ bp+si bx+di 8
+ */
+ if((FirstIndex == Register_bp && SecondIndex == Register_di) ||
+ (FirstIndex == Register_b && SecondIndex == Register_si))
+ {
+ AddedClocks += 7;
+ }
+ else
+ {
+ AddedClocks += 8;
+ }
+ }
+ // Base + index + displacement
+ else
+ {
+ /*
+ bp+di bx+si 11
+ bp+si bx+di 12
+ */
+ if((FirstIndex == Register_bp && SecondIndex == Register_di) ||
+ (FirstIndex == Register_b && SecondIndex == Register_si))
+ {
+ AddedClocks += 11;
+ }
+ else
+ {
+ AddedClocks += 12;
+ }
+ }
+
+ }
+
+ // Add transfer penalty
+ if(Clocks->Transfers && (Decoded.Flags & Inst_Wide))
+ {
+ instruction_operand *MemoryOperand = ((DestinationOperand->Type == Operand_Memory) ? DestinationOperand : SourceOperand);
+ s32 Displacement = GetCompleteDisplacement(Registers, MemoryOperand);
+ if(Displacement & 1)
+ {
+ AddedClocks += 4*Clocks->Transfers;
+ }
+ }
+
+ break;
+ }
+ }
+
+#if 0
+ Assert(AddedClocks);
+#endif
+
+ ElapsedClocks += AddedClocks;
+ printf(" clocks: +%d = %d", AddedClocks, ElapsedClocks);
+
s32 *Destination = OperandToValue(Registers, Memory, DestinationOperand);
s32 *Source = OperandToValue(Registers, Memory, SourceOperand);
@@ -207,8 +330,6 @@ Run8086(psize MemorySize, u8 *Memory)
}
else if(Decoded.Op == Op_add)
{
- Assert(DestinationOperand->Type == Operand_Register);
-
s32 Old = *Destination;
*Destination = ((Decoded.Flags & Inst_Wide) ?
@@ -257,7 +378,7 @@ Run8086(psize MemorySize, u8 *Memory)
}
- printf("Final registers:\n");
+ printf("\nFinal registers:\n");
for(u32 RegisterIndex = Register_a;
RegisterIndex < Register_ds + 1;
RegisterIndex++)
diff --git a/src/sim86.h b/src/sim86.h
index d24cb70..24068e2 100644
--- a/src/sim86.h
+++ b/src/sim86.h
@@ -12,27 +12,4 @@ typedef size_t psize;
#define Assert(Expression) if(!(Expression)) { __asm__ volatile("int3"); }
#define ArrayCount(Array) (sizeof(Array) / sizeof((Array)[0]))
-//~ Stolen from the decoder.
-enum register_mapping_8086
-{
- Register_none,
-
- Register_a,
- Register_b,
- Register_c,
- Register_d,
- Register_sp,
- Register_bp,
- Register_si,
- Register_di,
- Register_es,
- Register_cs,
- Register_ss,
- Register_ds,
- Register_ip,
- Register_flags,
-
- Register_count,
-};
-
#endif //SIM86_H
diff --git a/src/sim86.mdesk b/src/sim86.mdesk
index 6de46fc..0635110 100644
--- a/src/sim86.mdesk
+++ b/src/sim86.mdesk
@@ -1,4 +1,3 @@
-
@table(name, str) sim86_flags_mapping:
{
{ Carry, "C", }
@@ -12,21 +11,22 @@
{ Trap, "T", }
}
-@table(name, title) songs:
-{
- { French, "French Blues" },
- { Russian, "Russian Blues" },
-}
-
-@table_gen_enum_flags(songs, name) flags_songs
-@table_gen_data(songs, `char *`, title) songs_strings
-
@table_gen_enum_flags(sim86_flags_mapping, name) flags_8086
@table_gen_data(sim86_flags_mapping, `char *`, str) flags_8086_strings
+// TODO:
@table_gen_enum sim86_enum:
{
@expand(sim86_flags_mapping mapping)
`Sim86_$(mapping.name),`
`Sim86_Count`
-} \ No newline at end of file
+}
+
+@table(mnemonic, encoding, clocks, name) instructions_table:
+{
+ { mov, [ B:100010, D, W, MOD, REG, RM ], 4, "Register/memory to/from register" }
+ { mov, [ B:1100011, W, MOD, B:000, RM, ImpD:0, DATA, DATA_IF_W ], 5, "Immediate to register/memory" }
+ { mov, [ B:1011, W, REG, ImpD:1 ], 3, "Immediate to register" }
+}
+
+
diff --git a/src/sim86_meta.c b/src/sim86_meta.c
index f5046a7..c8fe8f3 100644
--- a/src/sim86_meta.c
+++ b/src/sim86_meta.c
@@ -123,6 +123,13 @@ int main(int ArgsCount, char *Args[])
MD_S8ListPush(Arena, &Stream, MD_S8Lit("};\n\n"));
}
+#if 0
+ if(MD_NodeHasTag(Node, MD_S8Lit("table"), 0))
+ {
+ Assert(0);
+ }
+#endif
+
if(MD_NodeHasTag(Node, MD_S8Lit("table_gen_enum"), 0))
{
// Header