wip, the urge to finish the lookup table is real...

This commit is contained in:
Edward R. Gonzalez 2023-03-06 07:33:25 -05:00
parent 356d8076a5
commit 3c712f8be6
15 changed files with 851 additions and 192 deletions

View File

@ -3,6 +3,7 @@
"*.rmd": "markdown", "*.rmd": "markdown",
"zpl.h": "c", "zpl.h": "c",
"cstddef": "cpp", "cstddef": "cpp",
"xtr1common": "cpp" "xtr1common": "cpp",
"*.inline": "cpp"
} }
} }

51
8086/Op.hpp Normal file
View File

@ -0,0 +1,51 @@
#include "bloat.hpp"
namespace Op
{
enum Code : u8
{
#define D_Entry( Entry_ ) Entry,
#include "opcodes.inline"
Num,
#undef D_Entry
};
char const* str( Code code )
{
static
char const* code_to_str[ Num] =
{
#define D_Entry( Entry_ ) ZPL_STRINGIFY( Entry_ ),
#include "opcodes.inline"
#undef D_Entry
};
return code_to_str[ code ];
}
char const* meumonic( Code code )
{
static
char const* code_to_str[ Num] =
{
#define D_Entry( Entry_ ) ZPL_STRINGIFY( Entry_ ),
#include "opcodes.meumonics.inline"
#undef D_Entry
};
return code_to_str[ code ];
}
char const* intuitive( Code code )
{
static
char const* code_to_str[ Num] =
{
#define D_Entry( Entry_ ) ZPL_STRINGIFY( Entry_ ),
#include "opcodes.intuitive.inline"
#undef D_Entry
};
return code_to_str[ Num];
}
}

146
8086/opcodes.inline Normal file
View File

@ -0,0 +1,146 @@
D_Entry( add_00 )
D_Entry( add_01 )
D_Entry( add_02 )
D_Entry( add_04 )
D_Entry( add_05 )
D_Entry( push_06 )
D_Entry( pop_07 )
D_Entry( or_10 )
D_Entry( or_11 )
D_Entry( or_12 )
D_Entry( or_13 )
D_Entry( or_14 )
D_Entry( or_15 )
D_Entry( push_16 )
D_Entry( _17 )
D_Entry( adc_20 )
D_Entry( adc_21 )
D_Entry( adc_22 )
D_Entry( adc_23 )
D_Entry( adc_24 )
D_Entry( adc_25 )
D_Entry( push_26 )
D_Entry( pop_27 )
D_Entry( sbb_30 )
D_Entry( sbb_31 )
D_Entry( sbb_32 )
D_Entry( sbb_33 )
D_Entry( sbb_34 )
D_Entry( sbb_35 )
D_Entry( push_36 )
D_Entry( pop_37 )
D_Entry( and_40 )
D_Entry( and_41 )
D_Entry( and_42 )
D_Entry( and_43 )
D_Entry( and_44 )
D_Entry( and_45 )
D_Entry( es_46 )
D_Entry( daa_47 )
D_Entry( sub_50 )
D_Entry( sub_51 )
D_Entry( sub_52 )
D_Entry( sub_53 )
D_Entry( sub_54 )
D_Entry( sub_55 )
D_Entry( cs_56 )
D_Entry( das_57 )
D_Entry( xor_60 )
D_Entry( xor_61 )
D_Entry( xor_62 )
D_Entry( xor_63 )
D_Entry( xor_64 )
D_Entry( xor_65 )
D_Entry( ss_66 )
D_Entry( aaa_67 )
D_Entry( cmp_70 )
D_Entry( cmp_71 )
D_Entry( cmp_72 )
D_Entry( cmp_73 )
D_Entry( cmp_74 )
D_Entry( cmp_75 )
D_Entry( ds_75 )
D_Entry( ds_76 )
D_Entry( aas_107 )
D_Entry( inc_100 )
D_Entry( inc_101 )
D_Entry( inc_102 )
D_Entry( inc_103 )
D_Entry( inc_104 )
D_Entry( inc_105 )
D_Entry( inc_106 )
D_Entry( inc_107 )
D_Entry( dec_100 )
D_Entry( dec_101 )
D_Entry( dec_102 )
D_Entry( dec_103 )
D_Entry( dec_104 )
D_Entry( dec_105 )
D_Entry( dec_106 )
D_Entry( dec_107 )
D_Entry( push_110 )
D_Entry( push_111 )
D_Entry( push_112 )
D_Entry( push_113 )
D_Entry( push_114 )
D_Entry( push_115 )
D_Entry( push_116 )
D_Entry( push_117 )
D_Entry( pop_120 )
D_Entry( pop_121 )
D_Entry( pop_122 )
D_Entry( pop_123 )
D_Entry( pop_124 )
D_Entry( pop_125 )
D_Entry( pop_126 )
D_Entry( pop_127 )
D_Entry( pop_130 )
D_Entry( pop_131 )
D_Entry( pop_132 )
D_Entry( pop_133 )
D_Entry( pop_134 )
D_Entry( pop_135 )
D_Entry( pop_136 )
D_Entry( pop_137 )
D_Entry( _140 )
D_Entry( _141 )
D_Entry( _142 )
D_Entry( _143 )
D_Entry( _144 )
D_Entry( _145 )
D_Entry( _146 )
D_Entry( _147 )
D_Entry( _150 )
D_Entry( _151 )
D_Entry( _152 )
D_Entry( _153 )
D_Entry( _154 )
D_Entry( _155 )
D_Entry( _156 )
D_Entry( _157 )
D_Entry( jo_160 )
D_Entry( jno_161 )
D_Entry( jb_jnae_jc_162 )
D_Entry( jnb_jae_jnc_163 )
D_Entry( je_jz_164 )
D_Entry( jne_jnz_165 )
D_Entry( jbe_jna_166 )
D_Entry( jnbe_ja_167 )
D_Entry( js_170 )
D_Entry( jns_171 )
D_Entry( jp_jpe_172 )
D_Entry( jnp_jpo_173 )
D_Entry( jl_jnge_174 )
D_Entry( jnl_jge_175 )
D_Entry( jle_jng_176 )
D_Entry( jnle_jg_177 )
D_Entry( add_200 )
D_Entry( or_201 )
D_Entry( adc_201 )
D_Entry( sbb_202 )
D_Entry( sub_203 )
D_Entry( cmp_204 )
D_Entry( add_205 )
D_Entry( adc_206 )
D_Entry( sbb_207 )
D_Entry( sub_210 )

View File

View File

View File

@ -30,22 +30,101 @@
// # define ZPL_MODULE_THREADING // # define ZPL_MODULE_THREADING
// # define ZPL_MODULE_JOBS // # define ZPL_MODULE_JOBS
// # define ZPL_MODULE_PARSER // # define ZPL_MODULE_PARSER
extern "C" { // extern "C" {
#include "zpl.h" #include "zpl.h"
} // }
#if __clang__ #if __clang__
# pragma clang diagnostic pop # pragma clang diagnostic pop
#endif #endif
#undef cast
#pragma endregion ZPL INCLUDE #pragma endregion ZPL INCLUDE
zpl_arena Global_Arena {};
#define g_allocator zpl_arena_allocator( & Global_Arena)
void setup()
{
zpl_arena_init_from_allocator( & Global_Arena, zpl_heap(), zpl_megabytes(10) );
if ( Global_Arena.total_size == 0 )
{
zpl_assert_crash( "Failed to reserve memory for Tests:: Global_Arena" );
}
}
void cleanup()
{
zpl_arena_free( & Global_Arena);
}
#pragma region ZPL Expose
zpl_string string_make(zpl_isize capacity)
{
zpl_isize header_size = zpl_size_of(zpl_string_header);
void *ptr = zpl_alloc(g_allocator, header_size + capacity + 1);
zpl_string str;
zpl_string_header *header;
if (ptr == NULL) return NULL;
zpl_zero_size(ptr, header_size + capacity + 1);
str = cast(char *) ptr + header_size;
header = ZPL_STRING_HEADER(str);
header->allocator = g_allocator;
header->length = 0;
header->capacity = capacity;
str[capacity] = '\0';
return str;
}
inline
zpl_string string_make(const char *str)
{
zpl_isize len = str ? zpl_strlen(str) : 0;
return zpl_string_make_length(g_allocator, str, len);
}
inline
zpl_string string_append(zpl_string str, zpl_string const other)
{
return zpl_string_append_length(str, other, zpl_string_length(other));
}
zpl_string string_format( char const* fmt, ... )
{
zpl_local_persist zpl_thread_local char buf[ZPL_PRINTF_MAXLEN] = { 0 };
va_list va;
va_start(va, fmt);
zpl_snprintf_va(buf, ZPL_PRINTF_MAXLEN, fmt, va);
va_end(va);
return zpl_string_make(g_allocator, buf);
}
zpl_string string_format( char* buffer, zpl_isize size, char const* fmt, ... )
{
va_list va;
va_start(va, fmt);
zpl_snprintf_va(buffer, size, fmt, va);
va_end(va);
return zpl_string_make(g_allocator, buffer);
}
#pragma endregion ZPL Expose
#define bit( Value_ ) ( 1 << Value_ ) #define bit( Value_ ) ( 1 << Value_ )
#define bitfield_is_equal( Field_, Mask_ ) ( ( Mask_ & Field_ ) == Mask_ ) #define bitfield_is_equal( Field_, Mask_ ) ( ( Mask_ & Field_ ) == Mask_ )
#undef cast
#define cast( Type_ , Value_ ) ( ( Type_ )( Value_ ) ) #define cast( Type_ , Value_ ) ( ( Type_ )( Value_ ) )
#define ct constexpr #define ct constexpr
#define gen( ... ) template< __VA_ARGS__ > #define gen( ... ) template< __VA_ARGS__ >
@ -54,13 +133,31 @@ extern "C" {
#define Msg_Invalid_Value "INVALID VALUE PROVIDED" #define Msg_Invalid_Value "INVALID VALUE PROVIDED"
#define scast static_cast #define scast static_cast
#define rcast reinterpret_cast #define rcast reinterpret_cast
#define pcast( Type_, Value_ ) ( * (Type_*)( & Value_ ) )
using s8 = zpl_i8;
using u8 = zpl_u8; using u8 = zpl_u8;
using u16 = zpl_u16; using u16 = zpl_u16;
using u32 = zpl_u32; using u32 = zpl_u32;
using f64 = zpl_f64;
using uw = zpl_usize; using uw = zpl_usize;
using sw = zpl_isize; using sw = zpl_isize;
struct u16_Split
{
u8 Low;
u8 High;
operator u16()
{
return * cast( u16*, this );
}
};
ct inline ct inline
char char_binary( u8 value, u8 pos ) char char_binary( u8 value, u8 pos )
{ {

View File

@ -15,5 +15,15 @@ if not exist tests\listing_0038_many_register_mov (
call nasm ".\tests\listing_0038_many_register_mov.asm" call nasm ".\tests\listing_0038_many_register_mov.asm"
) )
if not exist tests\listing_0039_more_movs (
echo Assembling: listing_0039_more_movs.asm
call nasm ".\tests\listing_0039_more_movs.asm"
)
if not exist tests\listing_0040_challenge_movs (
echo Assembling: listing_0040_challenge_movs.asm
call nasm ".\tests\listing_0040_challenge_movs.asm"
)
echo: echo:
ninja -C build ninja -C build

View File

@ -11,3 +11,12 @@ if exist tests\listing_0037_single_register_mov (
if exist tests\listing_0038_many_register_mov ( if exist tests\listing_0038_many_register_mov (
DEL /Q tests\listing_0038_many_register_mov DEL /Q tests\listing_0038_many_register_mov
) )
if exist tests\listing_0039_more_movs (
DEL /Q tests\listing_0039_more_movs
)
if exist tests\listing_0040_challenge_movs (
DEL /Q tests\listing_0040_challenge_movs
)

View File

@ -1,60 +1,46 @@
#include "bloat.hpp" #include "bloat.hpp"
zpl_arena BlobArena {}; // Octal formatting is used heavily throughout
#define allocator zpl_arena_allocator( & BlobArena) // See: https://gist.github.com/seanjensengrey/f971c20d05d4d0efc0781f2f3c0353da
// (x86 is an octal machine)
void setup()
{
zpl_arena_init_from_allocator( & BlobArena, zpl_heap(), zpl_megabytes(10) );
if ( BlobArena.total_size == 0 )
{
zpl_assert_crash( "Failed to reserve memory for Tests:: BLobArena" );
}
}
void cleanup()
{
zpl_arena_free( & BlobArena);
}
// Binary formatting for literals is used heavily as that its
// how the encoding is conveyed in the hardware reference from intel.
namespace Op namespace Op
{ {
ct u8 Mask = 00210;
ct u8 Mask_Low = 0b11110000;
ct u8 Mask_High = 0b00001111;
ct u8 Mask_Imme = 0b00111000;
#define D_Opcodes \ #define D_Opcodes \
D_Entry( mov_88 ) \ D_Entry( mov_RM_R ) \
D_Entry( mov_89 ) \ D_Entry( mov_Im_RM ) \
D_Entry( mov_Im_R ) \
D_Entry( mov_M_Acc ) \
D_Entry( mov_Acc_M ) \
D_Entry( mov_RM_SR ) \
D_Entry( mov_SR_RM ) \
enum Code : u8 enum Code : u8
{ {
Mask = 0b11111100, mov_RM_R = 0b10001000,
mov_88 = 0b10001000, mov_Im_RM = 0b11001100,
mov_89 = 0b11000100, mov_Im_R = 0b10110000,
mov_M_Acc = 0b10100000,
mov_Acc_M = 0b10100010,
mov_RM_SR = 0b10001110,
mov_SR_RM = 0b10001100
}; };
char const* str( Code type ) char const* str( Code type )
{ {
switch ( type ) switch ( type )
{ {
case mov_88: #define D_Entry( Entry_ ) \
return "mov_88"; case Entry_: \
case mov_89: return ZPL_STRINGIFY(Entry_); \
return "mov_89";
}
return Msg_Invalid_Value; D_Opcodes
} #undef D_Entry
ct char const* helper_meumonic( Code type )
{
switch ( type )
{
case mov_88:
case mov_89:
return "mov";
} }
return Msg_Invalid_Value; return Msg_Invalid_Value;
@ -64,32 +50,30 @@ namespace Op
{ {
switch ( type ) switch ( type )
{ {
case mov_88: case mov_RM_R :
case mov_89: case mov_Im_RM :
case mov_Im_R :
case mov_M_Acc :
case mov_Acc_M :
case mov_RM_SR :
case mov_SR_RM :
return "mov"; return "mov";
} }
return Msg_Invalid_Value; return Msg_Invalid_Value;
} }
ct char const* helper_intuitive( Code type )
{
switch ( type )
{
case mov_88:
case mov_89:
return "move";
}
return Msg_Invalid_Value;
}
char const* intuitive( Code type ) char const* intuitive( Code type )
{ {
switch ( type ) switch ( type )
{ {
case mov_88: case mov_RM_R :
case mov_89: case mov_Im_RM :
case mov_Im_R :
case mov_M_Acc :
case mov_Acc_M :
case mov_RM_SR :
case mov_SR_RM :
return "move"; return "move";
} }
@ -101,9 +85,8 @@ namespace Op
namespace Field namespace Field
{ {
// Effective Address offset
inline inline
u8 effective_address( u8 reg ) u8 offset_left_reg( u8 reg )
{ {
return reg << 3; return reg << 3;
} }
@ -135,6 +118,7 @@ namespace Field
enum Width : u8 enum Width : u8
{ {
Mask_Width = 0b00000001, Mask_Width = 0b00000001,
Mask_Width_Imme = 0b00001000,
Width_Byte = 0b00, Width_Byte = 0b00,
Width_Word = 0b01, Width_Word = 0b01,
}; };
@ -184,17 +168,61 @@ namespace Field
return Msg_Invalid_Value; return Msg_Invalid_Value;
} }
#if 0 ct u8 Mask_Memory = 0b00000111;
ct u8 RegMem_AL = 0b00000000;
ct u8 RegMem_AX = 0b00000000; // https://i.imgur.com/Tm5roJu.png
ct u8 RegMem_BX_SI = 0b00000000; enum Memory : u8
ct u8 RegMem_BX_SI_D8 = 0b00000000; {
ct u8 RegMem_BX_SI_D16 = 0b00000000; Add_BX_SI = 0b000,
#endif Add_BX_DI = 0b001,
Add_BP_SI = 0b010,
Add_BP_DI = 0b011,
Add_SI = 0b100,
Add_DI = 0b101,
Add_Direct = 0b110,
Add_BX = 0b111,
Num_Memory
};
char const* str_memory( Memory mem )
{
char const* mem_to_str[Num_Memory] =
{
"BX + SI",
"BX + DI",
"BP + SI",
"BP + DI",
"SI",
"DI",
"BP",
"BX"
};
return mem_to_str[ mem ];
}
char const* str_memory_intuitive( Memory mem )
{
char const* mem_to_str[Num_Memory] =
{
"Base.16 + Stack.Index",
"Base.16 + Destination.Index",
"Stack.Base + Stack.Index",
"Stack.Base + Destination.Index",
"Stack.Index",
"Destination.Index",
"Stack.Base",
"BX"
};
return mem_to_str[ mem ];
}
} }
namespace Register namespace Register
{ {
ct u8 Mask_Imme = 0b00000111;
ct u8 Mask_Left = 0b00111000; ct u8 Mask_Left = 0b00111000;
ct u8 Mask_Right = 0b00000111; ct u8 Mask_Right = 0b00000111;
@ -251,7 +279,7 @@ namespace Register
#undef D_Entry #undef D_Entry
}; };
return Type_To_Meumonic[ type + Width * 7 + 1 ]; return Type_To_Meumonic[ type + Width * ( 7 + 1 ) ];
} }
char const* intuitive( Type type, u8 Width ) char const* intuitive( Type type, u8 Width )
@ -259,38 +287,77 @@ namespace Register
static char const* static char const*
Type_To_Intuitive[ Num ] = Type_To_Intuitive[ Num ] =
{ {
"A.Low", "Accumulator.Low",
"C.Low", "Count.Low",
"D.Low", "Data.Low",
"B.Low", "Base.Low",
"A.High", "Accumulator.High",
"C.High", "Count.High",
"D.High", "Data.High",
"B.High", "Base.High",
"A.16", "Accumulator.16",
"C.16", "Count.16",
"D.16", "Data.16",
"B.16", "Base.16",
"Stack.Pointer", "Stack.Pointer",
"Stack.Base", "Stack.Base",
"Source.Index", "Source.Index",
"Destination.Index", "Destination.Index",
}; };
return Type_To_Intuitive[ type + Width * 7 + 1 ]; return Type_To_Intuitive[ type + Width * ( 7 + 1 ) ];
} }
} }
// 8086 Instructions are 1 to 6 bytes in length.
struct Octal
{
u8 Low : 3;
u8 High : 3;
u8 Dir : 1;
u8 Write : 1;
operator u8()
{
return * cast( u8*, this);
}
};
struct POD_Instruction struct POD_Instruction
{ {
u8 Byte_1; // 8086 Instructions are 1 to 6 bytes in length.
u8 Byte_2; union
u8 Byte_3; {
u8 Byte_4; u8* Ptr;
u8 Byte_5; u8 Byte[6];
u8 Byte_6;
Octal Instr;
struct
{
u8 Pad[2];
u16_Split Disp;
u16_Split Data;
}
EffAddr;
struct
{
u8 Pad[1];
u16_Split Data;
}
Imme;
struct
{
u8 Pad;
u16_Split Data;
}
Addr;
};
// If directly referencing blob data:
// Part of next instruction, do not use as stratch memory.
u16 Pad; u16 Pad;
}; };
@ -299,120 +366,232 @@ struct Instruction : public POD_Instruction
using Code = Op::Code; using Code = Op::Code;
using Direction = Field::Direction; using Direction = Field::Direction;
using Mode = Field::Mode; using Mode = Field::Mode;
using Memory = Field::Memory;
using Width = Field::Width; using Width = Field::Width;
using Reg = Register::Type; using Reg = Register::Type;
inline inline
Direction direction() Direction get_direction()
{ {
Direction Direction direction = cast(Direction, Byte[0] & Field::Mask_Dir);
direction = cast(Direction, Byte_1 & Field::Mask_Dir);
return direction; return direction;
} }
inline inline
Mode mode() Mode get_mode()
{ {
Mode mode = cast( Mode, Byte_2 & Field::Mask_Mode ); Mode mode = cast( Mode, Byte[1] & Field::Mask_Mode );
return mode; return mode;
} }
inline inline
Code opcode() Code get_opcode( u8 mask )
{ {
Op::Code Op::Code opcode = cast( Op::Code, Byte[0] & mask );
opcode = cast( Op::Code, Byte_1 & Op::Mask );
return opcode; return opcode;
} }
inline inline
Reg operand_left() Width get_width( u8 mask )
{
Width width = cast( Width, Byte[0] & mask );
return width;
}
inline
Reg mode_operand_left_reg()
{ {
u8 u8
operand = Byte_2 & Register::Mask_Left; operand = Byte[1] & Register::Mask_Left;
operand >>= 3; operand >>= 3;
return cast(Reg, operand); return cast(Reg, operand);
} }
inline inline
Reg operand_right() Reg mode_operand_right_reg()
{ {
u8 operand = Byte_2 & Register::Mask_Right; u8 operand = Byte[1] & Register::Mask_Right;
return cast( Reg, operand ); return cast( Reg, operand );
} }
inline forceinline
Width width() void dissassemble_mode( char const*& str_operand, Width& width, u8& length )
{
Width width = cast( Width, Byte_1 & Field::Mask_Width );
return width;
}
void dissassemble( zpl_string* result_out )
{ {
using namespace Field; using namespace Field;
using namespace Op; using namespace Op;
using namespace Register; using namespace Register;
Direction dir = direction(); switch ( get_mode() )
Width width_val = width(); {
case Mode_Mem:
{
Memory operand_right = cast( Memory, Byte[1] & Mask_Memory );
char const* opcode_str = Op::meumonic( opcode() ); length += 2;
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 );
char const* operand_right_str = Register::meumonic( operand_right(), width_val );
char if ( operand_right == Add_Direct )
binary_string[9]; {
binary_string[8] = '\0'; u16 address = EffAddr.Disp;
#if Build_Debug str_operand = string_format( "[ %u ]", address );
str_binary( binary_string, opcode() ); }
zpl_printf("\nOpcode : %s : %s", binary_string, opcode_str); else
{
str_operand = str_memory( operand_right );
}
}
break;
str_binary( binary_string, dir ); case Mode_Mem8:
zpl_printf("\nDirection : %s : %s", binary_string, direction_str); {
Memory operand_right = cast( Memory, Byte[1] & Mask_Memory );
str_binary( binary_string, width_val ); length += 1;
zpl_printf("\nWidth : %s : %s", binary_string, width_str);
str_binary( binary_string, mode() ); str_operand = string_format( "[ %s + %u ]", str_memory( operand_right), EffAddr.Disp.Low );
zpl_printf("\nMode : %s : %s", binary_string, mode_str); }
break;
str_binary( binary_string, operand_left() ); case Mode_Mem16:
zpl_printf("\nOperand : %s : %s", binary_string, operand_left_str); {
length += 2;
str_binary( binary_string, operand_right() ); Memory operand_right = cast( Memory, Byte[1] & Mask_Memory );
zpl_printf("\nOperand EA : %s : %s", binary_string, operand_right_str); u16 address = EffAddr.Disp;
#endif
if ( result_out == nullptr ) str_operand = string_format( "[ %s + %u ]", str_memory( operand_right), address );
return; }
break;
if ( * result_out == nullptr ) case Mode_Reg:
* result_out = zpl_string_make_reserve( allocator, zpl_kilobytes(1) ); str_operand = Register::meumonic( mode_operand_right_reg(), width );
break;
}
}
zpl_string assembly = zpl_string_make_reserve( allocator, 32); u8 dissassemble( zpl_string* result_out )
{
using namespace Field;
using namespace Op;
using namespace Register;
assembly = zpl_string_sprintf( allocator, assembly, zpl_kilobytes(1) - 1, "\n%s %s, %s" u8 length = 1;
, opcode_str
, dir == Dir_Src ? operand_right_str : operand_left_str zpl_string assembly = string_make( 32);
, dir == Dir_Src ? operand_left_str : operand_right_str
Code code = get_opcode( Op::Mask );
Direction dir = get_direction();
char const* str_operand_left = nullptr;
char const* str_operand_right = nullptr;
const u8 code_low = Byte[0] & Op::Mask_Low;
const u8 code_high = Byte[0] & Op::Mask_High;
const u8 sig_imme = Byte[0] & Op::Mask_Imme;
if ( get_opcode( Op::Mask_Low ) == mov_Im_R )
{
Width width = get_width( Mask_Width_Imme );
Reg reg = cast(Reg, Byte[0] & Register::Mask_Right );
u16 immediate = width == Width_Byte ?
Imme.Data.Low : Imme.Data;
str_operand_left = Register::meumonic( reg, width );
str_operand_right = string_format( "%u", immediate );
}
else
{
switch ( code )
{
#pragma region mov
case mov_RM_R:
{
length++;
Width width = get_width( Mask_Width );
str_operand_left = Register::meumonic( mode_operand_left_reg(), width );
dissassemble_mode( str_operand_right, width, length );
}
break;
case mov_Im_RM:
{
Width width = get_width( Mask_Width_Imme );
Memory operand_left = cast( Memory, Byte[1] & Mask_Memory );
u16 address = EffAddr.Disp;
u16 immediate = width == Width_Byte ?
EffAddr.Data.Low : EffAddr.Data;
dissassemble_mode( str_operand_left, width, length );
str_operand_right = string_format( "%u", immediate );
}
break;
case mov_M_Acc:
{
Width width = get_width( Mask_Width );
u16 address = width == Width_Byte ?
Addr.Data.Low : Addr.Data;
str_operand_left = Register::meumonic( Reg::AX, Width_Word );
str_operand_right = string_format( "%u", address );
}
break;
case mov_Acc_M:
{
Width width = get_width( Mask_Width );
u16 address = width == Width_Byte ?
Addr.Data.Low : Addr.Data;
str_operand_right = string_format( "%u", address );
str_operand_left = Register::meumonic( Reg::AX, Width_Word );
}
break;
case mov_RM_SR:
{
}
break;
case mov_SR_RM:
{
}
break;
#pragma endregion mov
}
}
assembly = string_format( assembly, 32, "\n%s %s, %s"
// opcode operand_right, operand_left
, Op::meumonic( code)
, str_operand_right
, str_operand_left
); );
* result_out = zpl_string_append( * result_out, assembly ); if ( result_out == nullptr )
return length;
if ( * result_out == nullptr )
* result_out = string_make( zpl_kilobytes(1) );
* result_out = string_append( * result_out, assembly );
#if Build_Debug
zpl_printf("\n\nAssembly: %s\n\n", assembly); zpl_printf("\n\nAssembly: %s\n\n", assembly);
#endif
return length;
} }
}; };
@ -426,14 +605,14 @@ namespace Tests
Instruction Instruction
mock; // mov CX, BX mock; // mov CX, BX
mock.Byte_1 = mov_88 | Dir_Src | Field::Width_Word; mock.Byte[0] = mov_RM_R | Dir_Src | Field::Width_Word;
mock.Byte_2 = Field::Mode_Reg | effective_address(BX) | CX; mock.Byte[1] = Field::Mode_Reg | offset_left_reg(BX) | CX;
zpl_printf("\n\nAttempting Mock Instruction: mov CX, BX"); zpl_printf("\n\nAttempting Mock Instruction: mov CX, BX");
print_nl(); print_nl();
print_as_binary( & mock.Byte_1, 1, " " ); print_as_binary( & mock.Byte[0], 1, " " );
print_as_binary( & mock.Byte_2, 1, " " ); print_as_binary( & mock.Byte[1], 1, " " );
print_nl(); print_nl();
zpl_string dissasembly = nullptr; zpl_string dissasembly = nullptr;
@ -441,12 +620,12 @@ namespace Tests
mock.dissassemble( & dissasembly); mock.dissassemble( & dissasembly);
} }
void try_blob_single_instruction() void try_blob_single_move()
{ {
zpl_printf("\n\nAttempting to read blob: listing_0037_single_register_mov"); zpl_printf("\n\nAttempting to read blob: listing_0037_single_register_mov");
zpl_file_contents zpl_file_contents
blob = zpl_file_read_contents( allocator, false, "tests/listing_0037_single_register_mov" ); blob = zpl_file_read_contents( g_allocator, false, "tests/listing_0037_single_register_mov" );
if (blob.data == nullptr ) if (blob.data == nullptr )
return; return;
@ -462,17 +641,17 @@ namespace Tests
Instruction Instruction
instr; instr;
instr.Byte_1 = data[0]; instr.Byte[0] = data[0];
instr.Byte_2 = data[1]; instr.Byte[1] = data[1];
instr.dissassemble( & dissasembly); instr.dissassemble( & dissasembly);
} }
void try_blob_many_instructions() void try_blob_many_moves()
{ {
zpl_printf("\n\nAttempting to read blob: listing_0038_many_register_mov"); zpl_printf("\n\nAttempting to read blob: listing_0038_many_register_mov");
zpl_file_contents zpl_file_contents
blob = zpl_file_read_contents( allocator, false, "tests/listing_0038_many_register_mov" ); blob = zpl_file_read_contents( g_allocator, false, "tests/listing_0038_many_register_mov" );
if (blob.data == nullptr ) if (blob.data == nullptr )
return; return;
@ -484,14 +663,14 @@ namespace Tests
print_as_binary( data, left, " " ); print_as_binary( data, left, " " );
print_nl(); print_nl();
zpl_string dissasembly = zpl_string_make( allocator, "bits 16\n"); zpl_string dissasembly = string_make( "bits 16\n");
while ( left ) while ( left )
{ {
Instruction Instruction
instr; instr;
instr.Byte_1 = data[0]; instr.Byte[0] = data[0];
instr.Byte_2 = data[1]; instr.Byte[1] = data[1];
instr.dissassemble( & dissasembly); instr.dissassemble( & dissasembly);
data += 2; data += 2;
@ -509,7 +688,47 @@ namespace Tests
); );
} }
#undef allocator void try_blob_more_moves()
{
zpl_printf("\n\nAttempting to read blob: listing_0039_more_movs");
zpl_file_contents
blob = zpl_file_read_contents( g_allocator, false, "tests/listing_0039_more_movs" );
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 = string_make( "bits 16\n");
while ( left )
{
Instruction
instr;
instr.Ptr = data;
u8 length = instr.dissassemble( & dissasembly);
data += length;
left -= length;
}
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_0039_more_movs.asm.out.asm"
, dissasembly
, zpl_string_length(dissasembly)
, nullptr
);
}
} }
@ -519,16 +738,14 @@ int main()
setup(); setup();
zpl_f64 start = zpl_time_rel(); f64 start = zpl_time_rel();
#if 0 // Tests::try_blob_single_move();
Tests::try_mock_instruction(); // Tests::try_blob_many_moves();
Tests::try_blob_single_instruction(); Tests::try_blob_more_moves();
#endif
Tests::try_blob_many_instructions();
zpl_f64 end = zpl_time_rel(); f64 end = zpl_time_rel();
zpl_f64 ms = (end - start) * 100; f64 ms = (end - start) * 100;
printf("\n\nElapsed Time: %lf ms", ms); printf("\n\nElapsed Time: %lf ms", ms);
printf("\n\n"); printf("\n\n");

View File

@ -1,12 +1,12 @@
bits 16 bits 16
mov CX, BX mov CX, BX
mov DH, CH mov CH, AH
mov DX, BX mov DX, BX
mov SI, BX mov SI, BX
mov BX, DI mov BX, DI
mov CL, DL mov AL, CL
mov DH, DH mov CH, CH
mov BX, AX mov BX, AX
mov BX, SI mov BX, SI
mov SP, DI mov SP, DI

Binary file not shown.

View File

@ -0,0 +1,47 @@
; ========================================================================
;
; (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 39
; ========================================================================
bits 16
; Register-to-register
mov si, bx
mov dh, al
; 8-bit immediate-to-register
mov cl, 12
mov ch, -12
; 16-bit immediate-to-register
mov cx, 12
mov cx, -12
mov dx, 3948
mov dx, -3948
; Source address calculation
mov al, [bx + si]
mov bx, [bp + di]
mov dx, [bp]
; Source address calculation plus 8-bit displacement
mov ah, [bx + si + 4]
; Source address calculation plus 16-bit displacement
mov al, [bx + si + 4999]
; Dest address calculation
mov [bx + di], cx
mov [bp + si], cl
mov [bp], ch

View File

@ -0,0 +1,43 @@
bits 16
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),

Binary file not shown.

View File

@ -0,0 +1,38 @@
; ========================================================================
;
; (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 40
; ========================================================================
bits 16
; Signed displacements
mov ax, [bx + di - 37]
mov [si - 300], cx
mov dx, [bx - 32]
; Explicit sizes
mov [bp + di], byte 7
mov [di + 901], word 347
; Direct address
mov bp, [5]
mov bx, [3458]
; Memory-to-accumulator test
mov ax, [2555]
mov ax, [16]
; Accumulator-to-memory test
mov [2554], ax
mov [15], ax