2023-03-05 17:57:40 -08:00
|
|
|
#include "bloat.hpp"
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
zpl_arena BlobArena {};
|
|
|
|
#define allocator zpl_arena_allocator( & BlobArena)
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
void setup()
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
zpl_arena_init_from_allocator( & BlobArena, zpl_heap(), zpl_megabytes(10) );
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
if ( BlobArena.total_size == 0 )
|
|
|
|
{
|
|
|
|
zpl_assert_crash( "Failed to reserve memory for Tests:: BLobArena" );
|
|
|
|
}
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
void cleanup()
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
zpl_arena_free( & BlobArena);
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
// Binary formatting for literals is used heavily as that its
|
|
|
|
// how the encoding is conveyed in the hardware reference from intel.
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
namespace Op
|
|
|
|
{
|
|
|
|
|
|
|
|
#define D_Opcodes \
|
|
|
|
D_Entry( mov_88 ) \
|
|
|
|
D_Entry( mov_89 ) \
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
enum Code : u8
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
Mask = 0b11111100,
|
2023-03-03 03:43:41 -08:00
|
|
|
mov_88 = 0b10001000,
|
|
|
|
mov_89 = 0b11000100,
|
|
|
|
};
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
char const* str( Code type )
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
switch ( type )
|
|
|
|
{
|
|
|
|
case mov_88:
|
|
|
|
return "mov_88";
|
|
|
|
case mov_89:
|
|
|
|
return "mov_89";
|
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return Msg_Invalid_Value;
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
ct char const* helper_meumonic( Code type )
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
switch ( type )
|
|
|
|
{
|
|
|
|
case mov_88:
|
|
|
|
case mov_89:
|
|
|
|
return "mov";
|
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return Msg_Invalid_Value;
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
char const* meumonic( Code type )
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
switch ( type )
|
|
|
|
{
|
|
|
|
case mov_88:
|
|
|
|
case mov_89:
|
|
|
|
return "mov";
|
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return Msg_Invalid_Value;
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
ct char const* helper_intuitive( Code type )
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
switch ( type )
|
|
|
|
{
|
|
|
|
case mov_88:
|
|
|
|
case mov_89:
|
|
|
|
return "move";
|
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return Msg_Invalid_Value;
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
char const* intuitive( Code type )
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
switch ( type )
|
|
|
|
{
|
|
|
|
case mov_88:
|
|
|
|
case mov_89:
|
|
|
|
return "move";
|
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return Msg_Invalid_Value;
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#undef D_Opcodes
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace Field
|
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
// Effective Address offset
|
|
|
|
inline
|
|
|
|
u8 effective_address( u8 reg )
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
return reg << 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://i.imgur.com/drsyYnM.png
|
2023-03-05 17:57:40 -08:00
|
|
|
enum Direction : u8
|
|
|
|
{
|
|
|
|
Mask_Dir = 0b00000010,
|
|
|
|
Dir_Src = 0b00,
|
|
|
|
Dir_Dest = 0b10,
|
|
|
|
};
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
inline
|
2023-03-05 17:57:40 -08:00
|
|
|
char const* str_direction( Direction direction )
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
switch ( direction )
|
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
case Dir_Dest:
|
2023-03-03 03:43:41 -08:00
|
|
|
return "Destination";
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
case Dir_Src:
|
2023-03-03 03:43:41 -08:00
|
|
|
return "Source";
|
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return Msg_Invalid_Value;
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// https://i.imgur.com/9Op8Lnd.png
|
2023-03-05 17:57:40 -08:00
|
|
|
enum Width : u8
|
|
|
|
{
|
|
|
|
Mask_Width = 0b00000001,
|
|
|
|
Width_Byte = 0b00,
|
|
|
|
Width_Word = 0b01,
|
|
|
|
};
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
inline
|
2023-03-05 17:57:40 -08:00
|
|
|
char const* str_width( Width width )
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
switch ( width )
|
|
|
|
{
|
|
|
|
case Width_Byte:
|
|
|
|
return "Byte";
|
|
|
|
|
|
|
|
case Width_Word:
|
|
|
|
return "Word";
|
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return Msg_Invalid_Value;
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// https://i.imgur.com/Job2oPd.png
|
2023-03-05 17:57:40 -08:00
|
|
|
enum Mode : u8
|
|
|
|
{
|
|
|
|
Mask_Mode = 0b11000000,
|
|
|
|
Mode_Mem = 0b00000000,
|
|
|
|
Mode_Mem8 = 0b01000000,
|
|
|
|
Mode_Mem16 = 0b10000000,
|
|
|
|
Mode_Reg = 0b11000000,
|
|
|
|
};
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
char const* str_mode( Mode mode )
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case Mode_Mem:
|
|
|
|
return "Memory: No Displacement";
|
|
|
|
|
|
|
|
case Mode_Mem8:
|
|
|
|
return "Memory: 8-bit Displacment";
|
|
|
|
|
|
|
|
case Mode_Mem16:
|
|
|
|
return "Memory: 16-bit Displacement";
|
|
|
|
|
|
|
|
case Mode_Reg:
|
|
|
|
return "Register";
|
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return Msg_Invalid_Value;
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
ct u8 RegMem_AL = 0b00000000;
|
|
|
|
ct u8 RegMem_AX = 0b00000000;
|
|
|
|
ct u8 RegMem_BX_SI = 0b00000000;
|
|
|
|
ct u8 RegMem_BX_SI_D8 = 0b00000000;
|
|
|
|
ct u8 RegMem_BX_SI_D16 = 0b00000000;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace Register
|
|
|
|
{
|
|
|
|
ct u8 Mask_Left = 0b00111000;
|
|
|
|
ct u8 Mask_Right = 0b00000111;
|
|
|
|
|
|
|
|
#define D_Opcodes \
|
|
|
|
D_Entry( AL ) \
|
|
|
|
D_Entry( CL ) \
|
|
|
|
D_Entry( DL ) \
|
|
|
|
D_Entry( BL ) \
|
|
|
|
D_Entry( AH ) \
|
|
|
|
D_Entry( CH ) \
|
|
|
|
D_Entry( DH ) \
|
|
|
|
D_Entry( BH ) \
|
|
|
|
D_Entry( AX ) \
|
|
|
|
D_Entry( CX ) \
|
|
|
|
D_Entry( DX ) \
|
|
|
|
D_Entry( BX ) \
|
|
|
|
D_Entry( SP ) \
|
|
|
|
D_Entry( BP ) \
|
|
|
|
D_Entry( SI ) \
|
|
|
|
D_Entry( DI ) \
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
enum Type : u8
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
AL = 0b000,
|
|
|
|
CL = 0b001,
|
|
|
|
DL = 0b010,
|
|
|
|
BL = 0b011,
|
|
|
|
|
|
|
|
AH = 0b100,
|
|
|
|
CH = 0b101,
|
|
|
|
DH = 0b110,
|
|
|
|
BH = 0b111,
|
|
|
|
|
|
|
|
AX = 0b000,
|
|
|
|
CX = 0b001,
|
|
|
|
DX = 0b010,
|
|
|
|
BX = 0b011,
|
|
|
|
|
|
|
|
SP = 0b100,
|
|
|
|
BP = 0b101,
|
|
|
|
SI = 0b110,
|
|
|
|
DI = 0b111,
|
|
|
|
|
|
|
|
Num = 16
|
|
|
|
};
|
|
|
|
|
|
|
|
char const* meumonic( Type type, u8 Width )
|
|
|
|
{
|
|
|
|
static char const*
|
|
|
|
Type_To_Meumonic[ Num ] =
|
|
|
|
{
|
|
|
|
#define D_Entry( Entry_ ) #Entry_,
|
|
|
|
D_Opcodes
|
|
|
|
#undef D_Entry
|
|
|
|
};
|
|
|
|
|
|
|
|
return Type_To_Meumonic[ type + Width * 7 + 1 ];
|
|
|
|
}
|
|
|
|
|
|
|
|
char const* intuitive( Type type, u8 Width )
|
|
|
|
{
|
|
|
|
static char const*
|
|
|
|
Type_To_Intuitive[ Num ] =
|
|
|
|
{
|
|
|
|
"A.Low",
|
|
|
|
"C.Low",
|
|
|
|
"D.Low",
|
|
|
|
"B.Low",
|
|
|
|
"A.High",
|
|
|
|
"C.High",
|
|
|
|
"D.High",
|
|
|
|
"B.High",
|
|
|
|
"A.16",
|
|
|
|
"C.16",
|
|
|
|
"D.16",
|
|
|
|
"B.16",
|
|
|
|
"Stack.Pointer",
|
|
|
|
"Stack.Base",
|
|
|
|
"Source.Index",
|
|
|
|
"Destination.Index",
|
|
|
|
};
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return Type_To_Intuitive[ type + Width * 7 + 1 ];
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 8086 Instructions are 1 to 6 bytes in length.
|
|
|
|
struct POD_Instruction
|
|
|
|
{
|
|
|
|
u8 Byte_1;
|
|
|
|
u8 Byte_2;
|
|
|
|
u8 Byte_3;
|
|
|
|
u8 Byte_4;
|
|
|
|
u8 Byte_5;
|
|
|
|
u8 Byte_6;
|
|
|
|
|
|
|
|
u16 Pad;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Instruction : public POD_Instruction
|
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
using Code = Op::Code;
|
|
|
|
using Direction = Field::Direction;
|
|
|
|
using Mode = Field::Mode;
|
|
|
|
using Width = Field::Width;
|
|
|
|
using Reg = Register::Type;
|
|
|
|
|
2023-03-03 03:43:41 -08:00
|
|
|
inline
|
2023-03-05 17:57:40 -08:00
|
|
|
Direction direction()
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
Direction
|
|
|
|
direction = cast(Direction, Byte_1 & Field::Mask_Dir);
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
return direction;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline
|
2023-03-05 17:57:40 -08:00
|
|
|
Mode mode()
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
Mode mode = cast( Mode, Byte_2 & Field::Mask_Mode );
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
return mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline
|
2023-03-05 17:57:40 -08:00
|
|
|
Code opcode()
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
Op::Code
|
|
|
|
opcode = cast( Op::Code, Byte_1 & Op::Mask );
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
return opcode;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline
|
2023-03-05 17:57:40 -08:00
|
|
|
Reg operand_left()
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
u8
|
|
|
|
operand = Byte_2 & Register::Mask_Left;
|
|
|
|
operand >>= 3;
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return cast(Reg, operand);
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline
|
2023-03-05 17:57:40 -08:00
|
|
|
Reg operand_right()
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
u8 operand = Byte_2 & Register::Mask_Right;
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
return cast( Reg, operand );
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline
|
2023-03-05 17:57:40 -08:00
|
|
|
Width width()
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
Width width = cast( Width, Byte_1 & Field::Mask_Width );
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
return width;
|
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
void dissassemble( zpl_string* result_out )
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
using namespace Field;
|
|
|
|
using namespace Op;
|
|
|
|
using namespace Register;
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
Direction dir = direction();
|
|
|
|
Width width_val = width();
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
char const* opcode_str = Op::meumonic( opcode() );
|
2023-03-05 17:57:40 -08:00
|
|
|
char const* direction_str = Field::str_direction( dir );
|
2023-03-03 03:43:41 -08:00
|
|
|
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 );
|
|
|
|
char const* operand_right_str = Register::meumonic( operand_right(), width_val );
|
|
|
|
|
|
|
|
char
|
|
|
|
binary_string[9];
|
|
|
|
binary_string[8] = '\0';
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
#if Build_Debug
|
2023-03-03 03:43:41 -08:00
|
|
|
str_binary( binary_string, opcode() );
|
|
|
|
zpl_printf("\nOpcode : %s : %s", binary_string, opcode_str);
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
str_binary( binary_string, dir );
|
2023-03-03 03:43:41 -08:00
|
|
|
zpl_printf("\nDirection : %s : %s", binary_string, direction_str);
|
|
|
|
|
|
|
|
str_binary( binary_string, width_val );
|
|
|
|
zpl_printf("\nWidth : %s : %s", binary_string, width_str);
|
|
|
|
|
|
|
|
str_binary( binary_string, mode() );
|
|
|
|
zpl_printf("\nMode : %s : %s", binary_string, mode_str);
|
|
|
|
|
|
|
|
str_binary( binary_string, operand_left() );
|
|
|
|
zpl_printf("\nOperand : %s : %s", binary_string, operand_left_str);
|
|
|
|
|
|
|
|
str_binary( binary_string, operand_right() );
|
|
|
|
zpl_printf("\nOperand EA : %s : %s", binary_string, operand_right_str);
|
2023-03-05 17:57:40 -08:00
|
|
|
#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
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace Tests
|
|
|
|
{
|
2023-03-05 17:57:40 -08:00
|
|
|
void try_mock_instruction()
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
using namespace Field;
|
|
|
|
using namespace Op;
|
|
|
|
using namespace Register;
|
|
|
|
|
|
|
|
Instruction
|
2023-03-05 17:57:40 -08:00
|
|
|
mock; // mov CX, BX
|
|
|
|
mock.Byte_1 = mov_88 | Dir_Src | Field::Width_Word;
|
|
|
|
mock.Byte_2 = Field::Mode_Reg | effective_address(BX) | CX;
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
zpl_printf("\n\nAttempting Mock Instruction: mov CX, BX");
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
print_nl();
|
|
|
|
print_as_binary( & mock.Byte_1, 1, " " );
|
|
|
|
print_as_binary( & mock.Byte_2, 1, " " );
|
|
|
|
print_nl();
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
zpl_string dissasembly = nullptr;
|
|
|
|
|
|
|
|
mock.dissassemble( & dissasembly);
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
void try_blob_single_instruction()
|
2023-03-03 03:43:41 -08:00
|
|
|
{
|
|
|
|
zpl_printf("\n\nAttempting to read blob: listing_0037_single_register_mov");
|
|
|
|
|
|
|
|
zpl_file_contents
|
2023-03-05 17:57:40 -08:00
|
|
|
blob = zpl_file_read_contents( allocator, false, "tests/listing_0037_single_register_mov" );
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
if (blob.data == nullptr )
|
|
|
|
return;
|
|
|
|
|
|
|
|
u32 left = blob.size;
|
2023-03-05 17:57:40 -08:00
|
|
|
u8* data = cast( u8*, blob.data );
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
print_nl();
|
|
|
|
print_as_binary( data, left, " " );
|
|
|
|
print_nl();
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
zpl_string dissasembly = nullptr;
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
Instruction
|
|
|
|
instr;
|
|
|
|
instr.Byte_1 = data[0];
|
|
|
|
instr.Byte_2 = data[1];
|
|
|
|
instr.dissassemble( & dissasembly);
|
|
|
|
}
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
void try_blob_many_instructions()
|
|
|
|
{
|
|
|
|
zpl_printf("\n\nAttempting to read blob: listing_0038_many_register_mov");
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
zpl_file_contents
|
|
|
|
blob = zpl_file_read_contents( allocator, false, "tests/listing_0038_many_register_mov" );
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
if (blob.data == nullptr )
|
|
|
|
return;
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
u32 left = blob.size;
|
|
|
|
u8* data = cast( u8*, blob.data );
|
|
|
|
|
|
|
|
print_nl();
|
|
|
|
print_as_binary( data, left, " " );
|
|
|
|
print_nl();
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
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;
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
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
|
|
|
|
);
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
2023-03-05 17:57:40 -08:00
|
|
|
|
|
|
|
#undef allocator
|
2023-03-03 03:43:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
zpl_printf("sim 8086!");
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
setup();
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
zpl_f64 start = zpl_time_rel();
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
#if 0
|
|
|
|
Tests::try_mock_instruction();
|
|
|
|
Tests::try_blob_single_instruction();
|
|
|
|
#endif
|
|
|
|
Tests::try_blob_many_instructions();
|
2023-03-03 03:43:41 -08:00
|
|
|
|
|
|
|
zpl_f64 end = zpl_time_rel();
|
2023-03-05 17:57:40 -08:00
|
|
|
zpl_f64 ms = (end - start) * 100;
|
2023-03-03 03:43:41 -08:00
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
printf("\n\nElapsed Time: %lf ms", ms);
|
2023-03-03 03:43:41 -08:00
|
|
|
printf("\n\n");
|
|
|
|
|
2023-03-05 17:57:40 -08:00
|
|
|
cleanup();
|
|
|
|
|
2023-03-03 03:43:41 -08:00
|
|
|
return 0;
|
|
|
|
}
|