mirror of
https://github.com/Ed94/perfaware.git
synced 2024-12-21 22:44:46 -08:00
Finished the first hw.
On to the second...
This commit is contained in:
parent
5b230d5653
commit
9be706b28d
19
.vscode/launch.json
vendored
Normal file
19
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(Windows) Launch",
|
||||
"type": "cppvsdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/part_1/build/sim_8086.exe",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceRoot}/part_1",
|
||||
"environment": [],
|
||||
"console": "externalTerminal"
|
||||
}
|
||||
]
|
||||
}
|
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -1,6 +1,8 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.rmd": "markdown",
|
||||
"zpl.h": "c"
|
||||
"zpl.h": "c",
|
||||
"cstddef": "cpp",
|
||||
"xtr1common": "cpp"
|
||||
}
|
||||
}
|
111
part_1/bloat.hpp
Normal file
111
part_1/bloat.hpp
Normal file
@ -0,0 +1,111 @@
|
||||
#if __clang__
|
||||
# pragma clang diagnostic ignored "-Wunused-const-variable"
|
||||
# pragma clang diagnostic ignored "-Wswitch"
|
||||
# pragma clang diagnostic ignored "-Wunused-variable"
|
||||
#endif
|
||||
|
||||
|
||||
#pragma region ZPL INCLUDE
|
||||
|
||||
#if __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wmissing-braces"
|
||||
# pragma clang diagnostic ignored "-Wbraced-scalar-init"
|
||||
#endif
|
||||
|
||||
#define ZPL_IMPLEMENTATION
|
||||
// # define ZPL_HEAP_ANALYSIS
|
||||
# define ZPL_NO_MATH_H
|
||||
# define ZPL_CUSTOM_MODULES
|
||||
# define ZPL_MODULE_ESSENTIALS
|
||||
# define ZPL_MODULE_CORE
|
||||
# define ZPL_MODULE_TIMER
|
||||
// # define ZPL_MODULE_HASHING
|
||||
// # define ZPL_MODULE_REGEX
|
||||
// # define ZPL_MODULE_EVENT
|
||||
// # define ZPL_MODULE_DLL
|
||||
// # define ZPL_MODULE_OPTS
|
||||
// # define ZPL_MODULE_PROCESS
|
||||
// # define ZPL_MODULE_MATH
|
||||
// # define ZPL_MODULE_THREADING
|
||||
// # define ZPL_MODULE_JOBS
|
||||
// # define ZPL_MODULE_PARSER
|
||||
extern "C" {
|
||||
#include "zpl.h"
|
||||
}
|
||||
|
||||
#if __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#undef cast
|
||||
|
||||
#pragma endregion ZPL INCLUDE
|
||||
|
||||
|
||||
|
||||
#define bit( Value_ ) ( 1 << Value_ )
|
||||
#define bitfield_is_equal( Field_, Mask_ ) ( ( Mask_ & Field_ ) == Mask_ )
|
||||
#define cast( Type_ , Value_ ) ( ( Type_ )( Value_ ) )
|
||||
#define ct constexpr
|
||||
#define gen( ... ) template< __VA_ARGS__ >
|
||||
#define forceinline ZPL_ALWAYS_INLINE
|
||||
#define print_nl( _) zpl_printf("\n")
|
||||
#define Msg_Invalid_Value "INVALID VALUE PROVIDED"
|
||||
#define scast static_cast
|
||||
#define rcast reinterpret_cast
|
||||
|
||||
using u8 = zpl_u8;
|
||||
using u16 = zpl_u16;
|
||||
using u32 = zpl_u32;
|
||||
using uw = zpl_usize;
|
||||
using sw = zpl_isize;
|
||||
|
||||
ct inline
|
||||
char char_binary( u8 value, u8 pos )
|
||||
{
|
||||
u8 mask = 1 << pos ;
|
||||
|
||||
return ( (1 << pos) & value) == mask ? '1' : '0';
|
||||
}
|
||||
|
||||
inline
|
||||
void str_binary( char* result, u8 value )
|
||||
{
|
||||
#if 0
|
||||
result[0] = char_binary( value, 0);
|
||||
result[1] = char_binary( value, 1);
|
||||
result[2] = char_binary( value, 2);
|
||||
result[3] = char_binary( value, 3);
|
||||
result[4] = char_binary( value, 4);
|
||||
result[5] = char_binary( value, 5);
|
||||
result[6] = char_binary( value, 6);
|
||||
result[7] = char_binary( value, 7);
|
||||
#else
|
||||
result[0] = char_binary( value, 7);
|
||||
result[1] = char_binary( value, 6);
|
||||
result[2] = char_binary( value, 5);
|
||||
result[3] = char_binary( value, 4);
|
||||
result[4] = char_binary( value, 3);
|
||||
result[5] = char_binary( value, 2);
|
||||
result[6] = char_binary( value, 1);
|
||||
result[7] = char_binary( value, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
void print_as_binary( u8* data, uw size, char const* byte_term )
|
||||
{
|
||||
char
|
||||
binary_string[9];
|
||||
binary_string[8] = '\0';
|
||||
|
||||
while ( size-- )
|
||||
{
|
||||
str_binary( binary_string, data[0]);
|
||||
|
||||
printf( "%s%s", binary_string, byte_term );
|
||||
|
||||
data += 1;
|
||||
}
|
||||
}
|
@ -4,4 +4,16 @@ if not exist build\nul (
|
||||
meson setup build
|
||||
)
|
||||
|
||||
echo:
|
||||
if not exist tests\listing_0037_single_register_mov (
|
||||
echo Assembling: listing_0037_single_register_mov.asm
|
||||
call nasm ".\tests\listing_0037_single_register_mov.asm"
|
||||
)
|
||||
|
||||
if not exist tests\listing_0038_many_register_mov (
|
||||
echo Assembling: listing_0038_many_register_mov.asm
|
||||
call nasm ".\tests\listing_0038_many_register_mov.asm"
|
||||
)
|
||||
|
||||
echo:
|
||||
ninja -C build
|
BIN
part_1/debug.rdbg
Normal file
BIN
part_1/debug.rdbg
Normal file
Binary file not shown.
@ -2,4 +2,12 @@ project( 'sim_8086', 'c', 'cpp', default_options : ['buildtype=debug'] )
|
||||
|
||||
include_thirdparty = include_directories( '../thirdparty' )
|
||||
|
||||
# add_global_arguments('-E', language : 'cpp')
|
||||
|
||||
if get_option('buildtype').startswith('debug')
|
||||
|
||||
add_project_arguments('-DBuild_Debug', language : 'cpp')
|
||||
|
||||
endif
|
||||
|
||||
executable( 'sim_8086', 'sim_8086.cpp', include_directories : include_thirdparty )
|
||||
|
@ -1,149 +1,42 @@
|
||||
#if __clang__
|
||||
#pragma clang diagnostic ignored "-Wunused-const-variable"
|
||||
#endif
|
||||
#include "bloat.hpp"
|
||||
|
||||
zpl_arena BlobArena {};
|
||||
#define allocator zpl_arena_allocator( & BlobArena)
|
||||
|
||||
#pragma region ZPL INCLUDE
|
||||
void setup()
|
||||
{
|
||||
zpl_arena_init_from_allocator( & BlobArena, zpl_heap(), zpl_megabytes(10) );
|
||||
|
||||
#if __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wmissing-braces"
|
||||
#pragma clang diagnostic ignored "-Wbraced-scalar-init"
|
||||
#endif
|
||||
if ( BlobArena.total_size == 0 )
|
||||
{
|
||||
zpl_assert_crash( "Failed to reserve memory for Tests:: BLobArena" );
|
||||
}
|
||||
}
|
||||
|
||||
#define ZPL_IMPLEMENTATION
|
||||
#include "zpl.h"
|
||||
void cleanup()
|
||||
{
|
||||
zpl_arena_free( & BlobArena);
|
||||
}
|
||||
|
||||
#if __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#pragma endregion ZPL INCLUDE
|
||||
|
||||
|
||||
// This has me screwing around with generating lookup tables.
|
||||
// Going to measure the difference between them and jump tables instructions at some point...
|
||||
|
||||
// Binary formatting for literals is used heavily as that is
|
||||
// Binary formatting for literals is used heavily as that its
|
||||
// how the encoding is conveyed in the hardware reference from intel.
|
||||
|
||||
|
||||
#define bit( value ) ( 1 << value )
|
||||
#define bitfield_is_equal( field_, mask_ ) ( ( mask_ & field_ ) == mask_ )
|
||||
#define ct constexpr
|
||||
#define forceinline ZPL_ALWAYS_INLINE
|
||||
#define MSG_INVALID_VALUE "INVALID VALUE PROVIDED"
|
||||
|
||||
|
||||
using u8 = unsigned char;
|
||||
using u16 = unsigned short;
|
||||
using u32 = unsigned long;
|
||||
|
||||
// using bytecode = u8;
|
||||
|
||||
|
||||
inline
|
||||
char char_binary( u8 value, u8 pos )
|
||||
{
|
||||
constexpr u8 baseline = 1;
|
||||
u8 mask = baseline << pos;
|
||||
|
||||
return ( (baseline << pos) & value) == mask ? '1' : '0';
|
||||
}
|
||||
|
||||
inline
|
||||
void str_binary( char* result, u8 value )
|
||||
{
|
||||
#if 0
|
||||
result[0] = char_binary( value, 0);
|
||||
result[1] = char_binary( value, 1);
|
||||
result[2] = char_binary( value, 2);
|
||||
result[3] = char_binary( value, 3);
|
||||
result[4] = char_binary( value, 4);
|
||||
result[5] = char_binary( value, 5);
|
||||
result[6] = char_binary( value, 6);
|
||||
result[7] = char_binary( value, 7);
|
||||
#else
|
||||
result[0] = char_binary( value, 7);
|
||||
result[1] = char_binary( value, 6);
|
||||
result[2] = char_binary( value, 5);
|
||||
result[3] = char_binary( value, 4);
|
||||
result[4] = char_binary( value, 3);
|
||||
result[5] = char_binary( value, 2);
|
||||
result[6] = char_binary( value, 1);
|
||||
result[7] = char_binary( value, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#define USE_LOOKUP_TABLE 0
|
||||
namespace Op
|
||||
{
|
||||
ct u8 Mask = 0b11111100;
|
||||
|
||||
#define D_Opcodes \
|
||||
D_Entry( mov_88 ) \
|
||||
D_Entry( mov_89 ) \
|
||||
|
||||
using Type = u8;
|
||||
enum
|
||||
enum Code : u8
|
||||
{
|
||||
#if USE_LOOKUP_TABLE
|
||||
#define D_Entry( Entry_ ) Entry_,
|
||||
D_Opcodes
|
||||
#undef D_Entry
|
||||
|
||||
#else
|
||||
Mask = 0b11111100,
|
||||
mov_88 = 0b10001000,
|
||||
mov_89 = 0b11000100,
|
||||
|
||||
#endif
|
||||
|
||||
Num = 2
|
||||
};
|
||||
|
||||
#if USE_LOOKUP_TABLE
|
||||
ct u8 code( Type type )
|
||||
char const* str( Code type )
|
||||
{
|
||||
constexpr u8
|
||||
type_to_code[ Num ] =
|
||||
{
|
||||
0b01000100, // mov_88
|
||||
0b11000100, // mov_89
|
||||
};
|
||||
|
||||
return type_to_code[ type ];
|
||||
}
|
||||
|
||||
ct u8 type( u8 code )
|
||||
{
|
||||
switch ( code )
|
||||
{
|
||||
#define D_Entry
|
||||
case 0b01000100:
|
||||
return mov_88;
|
||||
|
||||
#undef D_Entry
|
||||
}
|
||||
|
||||
return Num;
|
||||
}
|
||||
#endif
|
||||
|
||||
char const* str( Type type )
|
||||
{
|
||||
#if Op_USE_LOOKUP_TABLE
|
||||
static char const*
|
||||
type_to_str[ Num ] =
|
||||
{
|
||||
#define D_Entry( Entry_ ) #Entry_,
|
||||
D_Opcodes
|
||||
#undef D_Entry
|
||||
};
|
||||
|
||||
return type_to_str[ type ];
|
||||
|
||||
#else
|
||||
switch ( type )
|
||||
{
|
||||
case mov_88:
|
||||
@ -152,11 +45,10 @@ namespace Op
|
||||
return "mov_89";
|
||||
}
|
||||
|
||||
return MSG_INVALID_VALUE;
|
||||
#endif
|
||||
return Msg_Invalid_Value;
|
||||
}
|
||||
|
||||
ct char const* helper_meumonic( Type type )
|
||||
ct char const* helper_meumonic( Code type )
|
||||
{
|
||||
switch ( type )
|
||||
{
|
||||
@ -165,23 +57,11 @@ namespace Op
|
||||
return "mov";
|
||||
}
|
||||
|
||||
return MSG_INVALID_VALUE;
|
||||
return Msg_Invalid_Value;
|
||||
}
|
||||
|
||||
char const* meumonic( Type type )
|
||||
char const* meumonic( Code type )
|
||||
{
|
||||
#if USE_LOOKUP_TABLE
|
||||
static char const*
|
||||
type_to_meumonic[ Num ] =
|
||||
{
|
||||
#define D_Entry( Entry_ ) helper_meumonic( Entry_ ),
|
||||
D_Opcodes
|
||||
#undef D_Entry
|
||||
};
|
||||
|
||||
return type_to_meumonic[ type ];
|
||||
|
||||
#else
|
||||
switch ( type )
|
||||
{
|
||||
case mov_88:
|
||||
@ -189,11 +69,10 @@ namespace Op
|
||||
return "mov";
|
||||
}
|
||||
|
||||
return MSG_INVALID_VALUE;
|
||||
#endif
|
||||
return Msg_Invalid_Value;
|
||||
}
|
||||
|
||||
ct char const* helper_intuitive( Type type )
|
||||
ct char const* helper_intuitive( Code type )
|
||||
{
|
||||
switch ( type )
|
||||
{
|
||||
@ -202,24 +81,11 @@ namespace Op
|
||||
return "move";
|
||||
}
|
||||
|
||||
return MSG_INVALID_VALUE;
|
||||
return Msg_Invalid_Value;
|
||||
}
|
||||
|
||||
char const* intuitive( Type type )
|
||||
char const* intuitive( Code type )
|
||||
{
|
||||
#if USE_LOOKUP_TABLE
|
||||
static char const*
|
||||
type_to_meumonic[ Num ] =
|
||||
{
|
||||
#define D_Entry( Entry_ ) helper_intuitive( Entry_ ),
|
||||
D_Opcodes
|
||||
#undef D_Entry
|
||||
};
|
||||
|
||||
return type_to_meumonic[ type ];
|
||||
|
||||
#else
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case mov_88:
|
||||
@ -227,8 +93,7 @@ namespace Op
|
||||
return "move";
|
||||
}
|
||||
|
||||
return MSG_INVALID_VALUE;
|
||||
#endif
|
||||
return Msg_Invalid_Value;
|
||||
}
|
||||
|
||||
#undef D_Opcodes
|
||||
@ -236,51 +101,46 @@ namespace Op
|
||||
|
||||
namespace Field
|
||||
{
|
||||
#if 0
|
||||
using Type = u8;
|
||||
enum
|
||||
{
|
||||
Dir_REG_Dest = 0b00,
|
||||
Dir_REG_Src = 0b10,
|
||||
|
||||
|
||||
};
|
||||
#endif
|
||||
ct u8 Mask_Dir = 0b00000010;
|
||||
ct u8 Mask_Width = 0b00000001;
|
||||
ct u8 Mask_Mode = 0b11000000;
|
||||
|
||||
// Mask: Effective Address
|
||||
inline u8 mask_reg_operand( u8 reg )
|
||||
// Effective Address offset
|
||||
inline
|
||||
u8 effective_address( u8 reg )
|
||||
{
|
||||
return reg << 3;
|
||||
}
|
||||
|
||||
// https://i.imgur.com/drsyYnM.png
|
||||
ct u8 Dir_REG_Src = 0b00;
|
||||
ct u8 Dir_REG_Dest = 0b10;
|
||||
enum Direction : u8
|
||||
{
|
||||
Mask_Dir = 0b00000010,
|
||||
Dir_Src = 0b00,
|
||||
Dir_Dest = 0b10,
|
||||
};
|
||||
|
||||
inline
|
||||
char const* str_direction( u8 direction )
|
||||
char const* str_direction( Direction direction )
|
||||
{
|
||||
switch ( direction )
|
||||
{
|
||||
case Dir_REG_Dest:
|
||||
case Dir_Dest:
|
||||
return "Destination";
|
||||
|
||||
case Dir_REG_Src:
|
||||
case Dir_Src:
|
||||
return "Source";
|
||||
}
|
||||
|
||||
return MSG_INVALID_VALUE;
|
||||
return Msg_Invalid_Value;
|
||||
}
|
||||
|
||||
// https://i.imgur.com/9Op8Lnd.png
|
||||
ct u8 Width_Byte = 0b00;
|
||||
ct u8 Width_Word = 0b01;
|
||||
enum Width : u8
|
||||
{
|
||||
Mask_Width = 0b00000001,
|
||||
Width_Byte = 0b00,
|
||||
Width_Word = 0b01,
|
||||
};
|
||||
|
||||
inline
|
||||
char const* str_width( u8 width )
|
||||
char const* str_width( Width width )
|
||||
{
|
||||
switch ( width )
|
||||
{
|
||||
@ -291,16 +151,20 @@ namespace Field
|
||||
return "Word";
|
||||
}
|
||||
|
||||
return MSG_INVALID_VALUE;
|
||||
return Msg_Invalid_Value;
|
||||
}
|
||||
|
||||
// https://i.imgur.com/Job2oPd.png
|
||||
ct u8 Mode_Mem = 0b00000000;
|
||||
ct u8 Mode_Mem8 = 0b01000000;
|
||||
ct u8 Mode_Mem16 = 0b10000000;
|
||||
ct u8 Mode_Reg = 0b11000000;
|
||||
enum Mode : u8
|
||||
{
|
||||
Mask_Mode = 0b11000000,
|
||||
Mode_Mem = 0b00000000,
|
||||
Mode_Mem8 = 0b01000000,
|
||||
Mode_Mem16 = 0b10000000,
|
||||
Mode_Reg = 0b11000000,
|
||||
};
|
||||
|
||||
char const* str_mode( u8 mode )
|
||||
char const* str_mode( Mode mode )
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
@ -317,7 +181,7 @@ namespace Field
|
||||
return "Register";
|
||||
}
|
||||
|
||||
return MSG_INVALID_VALUE;
|
||||
return Msg_Invalid_Value;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -352,10 +216,8 @@ namespace Register
|
||||
D_Entry( SI ) \
|
||||
D_Entry( DI ) \
|
||||
|
||||
using Type = u8;
|
||||
enum
|
||||
enum Type : u8
|
||||
{
|
||||
// Endianness is prob wrong...
|
||||
AL = 0b000,
|
||||
CL = 0b001,
|
||||
DL = 0b010,
|
||||
@ -415,7 +277,7 @@ namespace Register
|
||||
"Destination.Index",
|
||||
};
|
||||
|
||||
return Type_To_Intuitive[ type + 8 * Width ];
|
||||
return Type_To_Intuitive[ type + Width * 7 + 1 ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,69 +296,75 @@ struct POD_Instruction
|
||||
|
||||
struct Instruction : public POD_Instruction
|
||||
{
|
||||
using Code = Op::Code;
|
||||
using Direction = Field::Direction;
|
||||
using Mode = Field::Mode;
|
||||
using Width = Field::Width;
|
||||
using Reg = Register::Type;
|
||||
|
||||
inline
|
||||
u8 direction()
|
||||
Direction direction()
|
||||
{
|
||||
u8 direction = Byte_1 & Field::Mask_Dir;
|
||||
Direction
|
||||
direction = cast(Direction, Byte_1 & Field::Mask_Dir);
|
||||
|
||||
return direction;
|
||||
}
|
||||
|
||||
inline
|
||||
u8 mode()
|
||||
Mode mode()
|
||||
{
|
||||
u8 mode = Byte_2 & Field::Mask_Mode;
|
||||
Mode mode = cast( Mode, Byte_2 & Field::Mask_Mode );
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
inline
|
||||
u8 opcode()
|
||||
Code opcode()
|
||||
{
|
||||
u8
|
||||
opcode = Byte_1 & Op::Mask;
|
||||
Op::Code
|
||||
opcode = cast( Op::Code, Byte_1 & Op::Mask );
|
||||
|
||||
return opcode;
|
||||
}
|
||||
|
||||
inline
|
||||
u8 operand_left()
|
||||
Reg operand_left()
|
||||
{
|
||||
u8
|
||||
operand = Byte_2 & Register::Mask_Left;
|
||||
operand >>= 3;
|
||||
|
||||
return operand;
|
||||
return cast(Reg, operand);
|
||||
}
|
||||
|
||||
inline
|
||||
u8 operand_right()
|
||||
Reg operand_right()
|
||||
{
|
||||
u8
|
||||
operand = Byte_2 & Register::Mask_Right;
|
||||
// operand <<= 1;
|
||||
u8 operand = Byte_2 & Register::Mask_Right;
|
||||
|
||||
return operand;
|
||||
return cast( Reg, operand );
|
||||
}
|
||||
|
||||
inline
|
||||
u8 width()
|
||||
Width width()
|
||||
{
|
||||
u8 width = Byte_1 & Field::Mask_Width;
|
||||
Width width = cast( Width, Byte_1 & Field::Mask_Width );
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
void disassemble()
|
||||
void dissassemble( zpl_string* result_out )
|
||||
{
|
||||
using namespace Field;
|
||||
using namespace Op;
|
||||
using namespace Register;
|
||||
|
||||
u8 width_val = width();
|
||||
Direction dir = direction();
|
||||
Width width_val = width();
|
||||
|
||||
char const* opcode_str = Op::meumonic( opcode() );
|
||||
char const* direction_str = Field::str_direction( direction() );
|
||||
char const* direction_str = Field::str_direction( dir );
|
||||
char const* width_str = Field::str_width( width_val );
|
||||
char const* mode_str = Field::str_mode( mode() );
|
||||
char const* operand_left_str = Register::meumonic( operand_left(), width_val );
|
||||
@ -506,10 +374,11 @@ struct Instruction : public POD_Instruction
|
||||
binary_string[9];
|
||||
binary_string[8] = '\0';
|
||||
|
||||
#if Build_Debug
|
||||
str_binary( binary_string, opcode() );
|
||||
zpl_printf("\nOpcode : %s : %s", binary_string, opcode_str);
|
||||
|
||||
str_binary( binary_string, direction() );
|
||||
str_binary( binary_string, dir );
|
||||
zpl_printf("\nDirection : %s : %s", binary_string, direction_str);
|
||||
|
||||
str_binary( binary_string, width_val );
|
||||
@ -523,107 +392,124 @@ struct Instruction : public POD_Instruction
|
||||
|
||||
str_binary( binary_string, operand_right() );
|
||||
zpl_printf("\nOperand EA : %s : %s", binary_string, operand_right_str);
|
||||
#endif
|
||||
|
||||
if ( result_out == nullptr )
|
||||
return;
|
||||
|
||||
if ( * result_out == nullptr )
|
||||
* result_out = zpl_string_make_reserve( allocator, zpl_kilobytes(1) );
|
||||
|
||||
zpl_string assembly = zpl_string_make_reserve( allocator, 32);
|
||||
|
||||
assembly = zpl_string_sprintf( allocator, assembly, zpl_kilobytes(1) - 1, "\n%s %s, %s"
|
||||
, opcode_str
|
||||
, dir == Dir_Src ? operand_right_str : operand_left_str
|
||||
, dir == Dir_Src ? operand_left_str : operand_right_str
|
||||
);
|
||||
|
||||
* result_out = zpl_string_append( * result_out, assembly );
|
||||
|
||||
#if Build_Debug
|
||||
zpl_printf("\n\nAssembly: %s\n\n", assembly);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
zpl_arena BlobArena {};
|
||||
void Init()
|
||||
{
|
||||
zpl_arena_init_from_allocator( & BlobArena, zpl_heap(), zpl_megabytes(1) );
|
||||
|
||||
if ( BlobArena.total_size == 0 )
|
||||
{
|
||||
zpl_assert_crash( "Failed to reserve memory for Tests:: BLobArena" );
|
||||
}
|
||||
}
|
||||
|
||||
void Try_MockInstruction()
|
||||
void try_mock_instruction()
|
||||
{
|
||||
using namespace Field;
|
||||
using namespace Op;
|
||||
using namespace Register;
|
||||
|
||||
Instruction
|
||||
mock; // mov AX, BX
|
||||
#if USE_LOOKUP_TABLE
|
||||
mock.Byte_1 = Op::code(mov_88) | Dir_REG_Dest | Field::Width_Word;
|
||||
#else
|
||||
mock.Byte_1 = mov_88 | Dir_REG_Src | Field::Width_Word;
|
||||
#endif
|
||||
mock.Byte_2 = Field::Mode_Reg | Field::mask_reg_operand(BX) | CX;
|
||||
mock; // mov CX, BX
|
||||
mock.Byte_1 = mov_88 | Dir_Src | Field::Width_Word;
|
||||
mock.Byte_2 = Field::Mode_Reg | effective_address(BX) | CX;
|
||||
|
||||
zpl_printf("\n\nAttempting Mock Instruction: mov CX, BX");
|
||||
|
||||
char
|
||||
binary_string[9];
|
||||
binary_string[8] = '\0';
|
||||
print_nl();
|
||||
print_as_binary( & mock.Byte_1, 1, " " );
|
||||
print_as_binary( & mock.Byte_2, 1, " " );
|
||||
print_nl();
|
||||
|
||||
str_binary( binary_string, mock.Byte_1 );
|
||||
zpl_printf("\n%s", binary_string);
|
||||
zpl_string dissasembly = nullptr;
|
||||
|
||||
str_binary( binary_string, mock.Byte_2 );
|
||||
zpl_printf("\n%s", binary_string);
|
||||
|
||||
mock.disassemble();
|
||||
mock.dissassemble( & dissasembly);
|
||||
}
|
||||
|
||||
void Try_Blob_SingleRegisterMove()
|
||||
void try_blob_single_instruction()
|
||||
{
|
||||
zpl_printf("\n\nAttempting to read blob: listing_0037_single_register_mov");
|
||||
|
||||
zpl_file_contents
|
||||
blob = zpl_file_read_contents( zpl_arena_allocator( & BlobArena), false,
|
||||
"tests/listing_0037_single_register_mov"
|
||||
// "tests/listing_0038_many_register_mov"
|
||||
);
|
||||
blob = zpl_file_read_contents( allocator, false, "tests/listing_0037_single_register_mov" );
|
||||
|
||||
if (blob.data == nullptr )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\nContents:\n");
|
||||
|
||||
u32 left = blob.size;
|
||||
u8* data = cast(u8*)blob.data
|
||||
// + blob.size - 1
|
||||
;
|
||||
u8* data = cast( u8*, blob.data );
|
||||
|
||||
char
|
||||
binary_string[9];
|
||||
binary_string[8] = '\0';
|
||||
print_nl();
|
||||
print_as_binary( data, left, " " );
|
||||
print_nl();
|
||||
|
||||
while ( left-- )
|
||||
{
|
||||
str_binary( binary_string, data[0]);
|
||||
|
||||
printf("%s\n", binary_string );
|
||||
|
||||
data += 1;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
left = blob.size;
|
||||
// data += blob.size;
|
||||
data -= blob.size;
|
||||
while ( left-- )
|
||||
{
|
||||
str_binary( binary_string, data[0]);
|
||||
|
||||
printf("%X", data[0] );
|
||||
|
||||
data += 1;
|
||||
}
|
||||
zpl_string dissasembly = nullptr;
|
||||
|
||||
Instruction
|
||||
instr;
|
||||
instr.Byte_1 = ((u8*)blob.data)[0];
|
||||
instr.Byte_2 = ((u8*)blob.data)[1];
|
||||
instr.disassemble();
|
||||
instr.Byte_1 = data[0];
|
||||
instr.Byte_2 = data[1];
|
||||
instr.dissassemble( & dissasembly);
|
||||
}
|
||||
|
||||
void try_blob_many_instructions()
|
||||
{
|
||||
zpl_printf("\n\nAttempting to read blob: listing_0038_many_register_mov");
|
||||
|
||||
zpl_file_contents
|
||||
blob = zpl_file_read_contents( allocator, false, "tests/listing_0038_many_register_mov" );
|
||||
|
||||
if (blob.data == nullptr )
|
||||
return;
|
||||
|
||||
u32 left = blob.size;
|
||||
u8* data = cast( u8*, blob.data );
|
||||
|
||||
print_nl();
|
||||
print_as_binary( data, left, " " );
|
||||
print_nl();
|
||||
|
||||
zpl_string dissasembly = zpl_string_make( allocator, "bits 16\n");
|
||||
|
||||
while ( left )
|
||||
{
|
||||
Instruction
|
||||
instr;
|
||||
instr.Byte_1 = data[0];
|
||||
instr.Byte_2 = data[1];
|
||||
instr.dissassemble( & dissasembly);
|
||||
|
||||
data += 2;
|
||||
left -= 2;
|
||||
}
|
||||
|
||||
zpl_printf("\n\nDissassemlby:\n%s", dissasembly);
|
||||
dissasembly = zpl_string_append_fmt( dissasembly, "\n" );
|
||||
|
||||
zpl_printf("\n\nSaving to file");
|
||||
zpl_file_write_contents("tests/listing_0038_many_register_mov.out.asm"
|
||||
, dissasembly
|
||||
, zpl_string_length(dissasembly)
|
||||
, nullptr
|
||||
);
|
||||
}
|
||||
|
||||
#undef allocator
|
||||
}
|
||||
|
||||
|
||||
@ -631,17 +517,23 @@ int main()
|
||||
{
|
||||
zpl_printf("sim 8086!");
|
||||
|
||||
Tests::Init();
|
||||
setup();
|
||||
|
||||
zpl_f64 start = zpl_time_rel();
|
||||
|
||||
Tests::Try_MockInstruction();
|
||||
Tests::Try_Blob_SingleRegisterMove();
|
||||
#if 0
|
||||
Tests::try_mock_instruction();
|
||||
Tests::try_blob_single_instruction();
|
||||
#endif
|
||||
Tests::try_blob_many_instructions();
|
||||
|
||||
zpl_f64 end = zpl_time_rel();
|
||||
zpl_f64 ms = (end - start) * 100;
|
||||
|
||||
printf("\n\nElapsed Time: %lf", end - start);
|
||||
printf("\n\nElapsed Time: %lf ms", ms);
|
||||
printf("\n\n");
|
||||
|
||||
cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
@echo off
|
||||
|
||||
echo Assembling: listing_0037_single_register_mov.asm
|
||||
call nasm ".\tests\listing_0037_single_register_mov.asm"
|
||||
|
||||
|
||||
echo Assembling: listing_0038_many_register_mov.asm
|
||||
call nasm ".\tests\listing_0038_many_register_mov.asm"
|
13
part_1/tests/listing_0038_many_register_mov.out.asm
Normal file
13
part_1/tests/listing_0038_many_register_mov.out.asm
Normal file
@ -0,0 +1,13 @@
|
||||
bits 16
|
||||
|
||||
mov CX, BX
|
||||
mov DH, CH
|
||||
mov DX, BX
|
||||
mov SI, BX
|
||||
mov BX, DI
|
||||
mov CL, DL
|
||||
mov DH, DH
|
||||
mov BX, AX
|
||||
mov BX, SI
|
||||
mov SP, DI
|
||||
mov BP, AX
|
Loading…
Reference in New Issue
Block a user