perfaware/part1: Remove unused defns, tidy up code
This commit is contained in:
		
							parent
							
								
									d7b6598b1c
								
							
						
					
					
						commit
						68486e8855
					
				
							
								
								
									
										217
									
								
								part1/sim8086.c
									
									
									
									
									
								
							
							
						
						
									
										217
									
								
								part1/sim8086.c
									
									
									
									
									
								
							| @ -7,31 +7,8 @@ | |||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| 
 | 
 | ||||||
| typedef struct S86_Buffer S86_Buffer; | // NOTE: Macros
 | ||||||
| struct S86_Buffer { | // ============================================================================
 | ||||||
|     char *data; |  | ||||||
|     size_t size; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef struct S86_Str8 S86_Str8; |  | ||||||
| struct S86_Str8 { |  | ||||||
|     char *data; |  | ||||||
|     size_t size; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef struct S86_Globals S86_Globals; |  | ||||||
| struct S86_Globals { |  | ||||||
|     HANDLE stdout_handle; |  | ||||||
|     bool   write_to_console; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef struct S86_BufferIterator { |  | ||||||
|     S86_Buffer buffer; |  | ||||||
|     size_t     index; |  | ||||||
| } S86_BufferIterator; |  | ||||||
| 
 |  | ||||||
| S86_Globals s86_globals; |  | ||||||
| 
 |  | ||||||
| #define S86_STRINGIFY2(token) #token | #define S86_STRINGIFY2(token) #token | ||||||
| #define S86_STRINGIFY(token) S86_STRINGIFY2(token) | #define S86_STRINGIFY(token) S86_STRINGIFY2(token) | ||||||
| #define S86_ASSERT(expr)                                                                         \ | #define S86_ASSERT(expr)                                                                         \ | ||||||
| @ -41,9 +18,38 @@ S86_Globals s86_globals; | |||||||
|     }                                                                                            \ |     }                                                                                            \ | ||||||
| 
 | 
 | ||||||
| #define S86_ARRAY_UCOUNT(array) sizeof((array)) / sizeof((array)[0]) | #define S86_ARRAY_UCOUNT(array) sizeof((array)) / sizeof((array)[0]) | ||||||
|  | #define S86_CAST(Type) (Type) | ||||||
|  | 
 | ||||||
|  | // NOTE: Globals
 | ||||||
|  | // ============================================================================
 | ||||||
|  | typedef struct S86_Globals { | ||||||
|  |     HANDLE stdout_handle; | ||||||
|  |     bool   write_to_console; | ||||||
|  | } S86_Globals; | ||||||
|  | 
 | ||||||
|  | S86_Globals s86_globals; | ||||||
|  | 
 | ||||||
|  | // NOTE: Strings
 | ||||||
|  | // ============================================================================
 | ||||||
|  | typedef struct S86_Str8 { | ||||||
|  |     char *data; | ||||||
|  |     size_t size; | ||||||
|  | } S86_Str8; | ||||||
|  | 
 | ||||||
| #define S86_STR8(string) (S86_Str8){.data = (string), .size = S86_ARRAY_UCOUNT(string) - 1 } | #define S86_STR8(string) (S86_Str8){.data = (string), .size = S86_ARRAY_UCOUNT(string) - 1 } | ||||||
| #define S86_STR8_FMT(string) (int)((string).size), (string).data | #define S86_STR8_FMT(string) (int)((string).size), (string).data | ||||||
| #define S86_CAST(Type) (Type) | 
 | ||||||
|  | // NOTE: Buffer
 | ||||||
|  | // ============================================================================
 | ||||||
|  | typedef struct S86_Buffer { | ||||||
|  |     char *data; | ||||||
|  |     size_t size; | ||||||
|  | } S86_Buffer; | ||||||
|  | 
 | ||||||
|  | typedef struct S86_BufferIterator { | ||||||
|  |     S86_Buffer buffer; | ||||||
|  |     size_t     index; | ||||||
|  | } S86_BufferIterator; | ||||||
| 
 | 
 | ||||||
| bool S86_BufferIsValid(S86_Buffer buffer); | bool S86_BufferIsValid(S86_Buffer buffer); | ||||||
| S86_BufferIterator S86_BufferIteratorInit(S86_Buffer buffer); | S86_BufferIterator S86_BufferIteratorInit(S86_Buffer buffer); | ||||||
| @ -51,11 +57,82 @@ bool S86_BufferIteratorHasMoreBytes(S86_BufferIterator it); | |||||||
| uint8_t S86_BufferIteratorPeekByte(S86_BufferIterator it); | uint8_t S86_BufferIteratorPeekByte(S86_BufferIterator it); | ||||||
| uint8_t S86_BufferIteratorNextByte(S86_BufferIterator *it); | uint8_t S86_BufferIteratorNextByte(S86_BufferIterator *it); | ||||||
| 
 | 
 | ||||||
|  | // NOTE: File
 | ||||||
|  | // ============================================================================
 | ||||||
| S86_Buffer S86_FileRead(char const *file_path); | S86_Buffer S86_FileRead(char const *file_path); | ||||||
| void S86_FileFree(S86_Buffer buffer); | void S86_FileFree(S86_Buffer buffer); | ||||||
|  | 
 | ||||||
|  | // NOTE: Print
 | ||||||
|  | // ============================================================================
 | ||||||
| void S86_PrintLn(S86_Str8 string); | void S86_PrintLn(S86_Str8 string); | ||||||
| void S86_PrintLnFmt(char const *fmt, ...); | void S86_PrintLnFmt(char const *fmt, ...); | ||||||
| 
 | 
 | ||||||
|  | // NOTE: Sim8086
 | ||||||
|  | // ============================================================================
 | ||||||
|  | typedef enum S86_InstructionType { | ||||||
|  |     S86_InstructionType_MOVRegOrMemToOrFromReg, | ||||||
|  |     S86_InstructionType_MOVImmediateToRegOrMem, | ||||||
|  |     S86_InstructionType_MOVImmediateToReg, | ||||||
|  |     S86_InstructionType_MOVMemToAccum, | ||||||
|  |     S86_InstructionType_MOVAccumToMem, | ||||||
|  |     S86_InstructionType_MOVRegOrMemToSegReg, | ||||||
|  |     S86_InstructionType_MOVSegRegToRegOrMem, | ||||||
|  |     S86_InstructionType_Count, | ||||||
|  | } S86_InstructionType; | ||||||
|  | 
 | ||||||
|  | /// Bit patterns and masks for decoding 8086 assembly. 8086 opcodes can be up
 | ||||||
|  | /// to 2 bytes long and mixed with instruction specific control bits. These
 | ||||||
|  | /// masks isolate the opcode bits from the bits can be checked after masking
 | ||||||
|  | /// the binary instruction stream.
 | ||||||
|  | ///
 | ||||||
|  | /// Instructions that do not have opcode bits in the 2nd byte will have the mask
 | ||||||
|  | /// set to 0.
 | ||||||
|  | typedef struct S86_Instruction { | ||||||
|  |     uint8_t op_mask0; | ||||||
|  |     uint8_t op_bits0; | ||||||
|  |     uint8_t op_mask1; | ||||||
|  |     uint8_t op_bits1; | ||||||
|  | } S86_Instruction; | ||||||
|  | 
 | ||||||
|  | S86_Instruction const S86_INSTRUCTIONS[S86_InstructionType_Count] = { | ||||||
|  |     [S86_InstructionType_MOVRegOrMemToOrFromReg] = {.op_mask0 = 0b1111'1100, | ||||||
|  |                                                     .op_bits0 = 0b1000'1000, | ||||||
|  |                                                     .op_mask1 = 0b0000'0000, | ||||||
|  |                                                     .op_bits1 = 0b0000'0000}, | ||||||
|  | 
 | ||||||
|  |     [S86_InstructionType_MOVImmediateToRegOrMem] = {.op_mask0 = 0b1111'1110, | ||||||
|  |                                                     .op_bits0 = 0b1100'0110, | ||||||
|  |                                                     .op_mask1 = 0b0011'1000, | ||||||
|  |                                                     .op_bits1 = 0b0000'0000}, | ||||||
|  | 
 | ||||||
|  |     [S86_InstructionType_MOVImmediateToReg]      = {.op_mask0 = 0b1111'0000, | ||||||
|  |                                                     .op_bits0 = 0b1011'0000, | ||||||
|  |                                                     .op_mask1 = 0b0000'0000, | ||||||
|  |                                                     .op_bits1 = 0b0000'0000}, | ||||||
|  | 
 | ||||||
|  |     [S86_InstructionType_MOVMemToAccum]          = {.op_mask0 = 0b1111'1110, | ||||||
|  |                                                     .op_bits0 = 0b1010'0000, | ||||||
|  |                                                     .op_mask1 = 0b0000'0000, | ||||||
|  |                                                     .op_bits1 = 0b0000'0000}, | ||||||
|  | 
 | ||||||
|  |     [S86_InstructionType_MOVAccumToMem]          = {.op_mask0 = 0b1111'1110, | ||||||
|  |                                                     .op_bits0 = 0b1010'0010, | ||||||
|  |                                                     .op_mask1 = 0b0000'0000, | ||||||
|  |                                                     .op_bits1 = 0b0000'0000}, | ||||||
|  | 
 | ||||||
|  |     [S86_InstructionType_MOVRegOrMemToSegReg]    = {.op_mask0 = 0b1111'1111, | ||||||
|  |                                                     .op_bits0 = 0b1000'1110, | ||||||
|  |                                                     .op_mask1 = 0b0010'0000, | ||||||
|  |                                                     .op_bits1 = 0b0000'0000}, | ||||||
|  | 
 | ||||||
|  |     [S86_InstructionType_MOVSegRegToRegOrMem]    = {.op_mask0 = 0b1111'1111, | ||||||
|  |                                                     .op_bits0 = 0b1000'1100, | ||||||
|  |                                                     .op_mask1 = 0b0010'0000, | ||||||
|  |                                                     .op_bits1 = 0b0000'0000}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // NOTE: Implementation
 | ||||||
|  | // ============================================================================
 | ||||||
| bool S86_BufferIsValid(S86_Buffer buffer) | bool S86_BufferIsValid(S86_Buffer buffer) | ||||||
| { | { | ||||||
|     bool result = buffer.data && buffer.size; |     bool result = buffer.data && buffer.size; | ||||||
| @ -208,76 +285,25 @@ void S86_PrintLnFmt(char const *fmt, ...) | |||||||
|     va_end(args); |     va_end(args); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| typedef enum S86_ModEncoding S86_ModEncoding; |  | ||||||
| enum S86_ModEncoding { |  | ||||||
|     S86_ModEncoding_MemModeNoDisplace = 0b00, |  | ||||||
|     S86_ModEncoding_MemMode8          = 0b01, |  | ||||||
|     S86_ModEncoding_MemMode16         = 0b10, |  | ||||||
|     S86_ModEncoding_RegisterMode      = 0b11, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef enum S86_InstructionType S86_InstructionType; |  | ||||||
| enum S86_InstructionType { |  | ||||||
|     S86_InstructionType_MOVRegOrMemToOrFromReg, |  | ||||||
|     S86_InstructionType_MOVImmediateToRegOrMem, |  | ||||||
|     S86_InstructionType_MOVImmediateToReg, |  | ||||||
|     S86_InstructionType_MOVMemToAccum, |  | ||||||
|     S86_InstructionType_MOVAccumToMem, |  | ||||||
|     S86_InstructionType_MOVRegOrMemToSegReg, |  | ||||||
|     S86_InstructionType_MOVSegRegToRegOrMem, |  | ||||||
|     S86_InstructionType_Count, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef struct S86_Instruction S86_Instruction; |  | ||||||
| struct S86_Instruction { |  | ||||||
|     uint8_t op_mask0; |  | ||||||
|     uint8_t op_bits0; |  | ||||||
|     uint8_t op_mask1; |  | ||||||
|     uint8_t op_bits1; |  | ||||||
| } S86_INSTRUCTIONS[S86_InstructionType_Count] = { |  | ||||||
|     [S86_InstructionType_MOVRegOrMemToOrFromReg] = {.op_mask0 = 0b1111'1100, |  | ||||||
|                                                     .op_bits0 = 0b1000'1000, |  | ||||||
|                                                     .op_mask1 = 0b0000'0000, |  | ||||||
|                                                     .op_bits1 = 0b0000'0000}, |  | ||||||
| 
 |  | ||||||
|     [S86_InstructionType_MOVImmediateToRegOrMem] = {.op_mask0 = 0b1111'1110, |  | ||||||
|                                                     .op_bits0 = 0b1100'0110, |  | ||||||
|                                                     .op_mask1 = 0b0011'1000, |  | ||||||
|                                                     .op_bits1 = 0b0000'0000}, |  | ||||||
| 
 |  | ||||||
|     [S86_InstructionType_MOVImmediateToReg]      = {.op_mask0 = 0b1111'0000, |  | ||||||
|                                                     .op_bits0 = 0b1011'0000, |  | ||||||
|                                                     .op_mask1 = 0b0000'0000, |  | ||||||
|                                                     .op_bits1 = 0b0000'0000}, |  | ||||||
| 
 |  | ||||||
|     [S86_InstructionType_MOVMemToAccum]          = {.op_mask0 = 0b1111'1110, |  | ||||||
|                                                     .op_bits0 = 0b1010'0000, |  | ||||||
|                                                     .op_mask1 = 0b0000'0000, |  | ||||||
|                                                     .op_bits1 = 0b0000'0000}, |  | ||||||
| 
 |  | ||||||
|     [S86_InstructionType_MOVAccumToMem]          = {.op_mask0 = 0b1111'1110, |  | ||||||
|                                                     .op_bits0 = 0b1010'0010, |  | ||||||
|                                                     .op_mask1 = 0b0000'0000, |  | ||||||
|                                                     .op_bits1 = 0b0000'0000}, |  | ||||||
| 
 |  | ||||||
|     [S86_InstructionType_MOVRegOrMemToSegReg]    = {.op_mask0 = 0b1111'1111, |  | ||||||
|                                                     .op_bits0 = 0b1000'1110, |  | ||||||
|                                                     .op_mask1 = 0b0010'0000, |  | ||||||
|                                                     .op_bits1 = 0b0000'0000}, |  | ||||||
| 
 |  | ||||||
|     [S86_InstructionType_MOVSegRegToRegOrMem]    = {.op_mask0 = 0b1111'1111, |  | ||||||
|                                                     .op_bits0 = 0b1000'1100, |  | ||||||
|                                                     .op_mask1 = 0b0010'0000, |  | ||||||
|                                                     .op_bits1 = 0b0000'0000}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| int main(int argc, char **argv) | int main(int argc, char **argv) | ||||||
| { | { | ||||||
|  |     // NOTE: Argument handling
 | ||||||
|  |     // =========================================================================
 | ||||||
|     if (argc != 2) { |     if (argc != 2) { | ||||||
|         S86_PrintLn(S86_STR8("usage: sim8086.exe <binary asm file>")); |         S86_PrintLn(S86_STR8("usage: sim8086.exe <binary asm file>")); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     char const *file_path = argv[1]; | ||||||
|  |     S86_Buffer buffer     = S86_FileRead(file_path); | ||||||
|  |     if (!S86_BufferIsValid(buffer)) { | ||||||
|  |         S86_PrintLnFmt("File read failed [path=\"%s\"]", argv[1], buffer.size); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // NOTE: Sim8086
 | ||||||
|  |     // =========================================================================
 | ||||||
|  |     // Mapping from a 'reg' encoding to the register name.
 | ||||||
|     S86_Str8 const REGISTER_FIELD_ENCODING[2][8] = { |     S86_Str8 const REGISTER_FIELD_ENCODING[2][8] = { | ||||||
|         [0b0] = |         [0b0] = | ||||||
|             { |             { | ||||||
| @ -303,13 +329,8 @@ int main(int argc, char **argv) | |||||||
|              }, |              }, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     char const *file_path = argv[1]; |     // NOTE: Decode assembly
 | ||||||
|     S86_Buffer buffer     = S86_FileRead(file_path); |     // =========================================================================
 | ||||||
|     if (!S86_BufferIsValid(buffer)) { |  | ||||||
|         S86_PrintLnFmt("File read failed [path=\"%s\"]", argv[1], buffer.size); |  | ||||||
|         return -1; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     S86_PrintLn(S86_STR8("bits 16")); |     S86_PrintLn(S86_STR8("bits 16")); | ||||||
|     S86_BufferIterator buffer_it = S86_BufferIteratorInit(buffer); |     S86_BufferIterator buffer_it = S86_BufferIteratorInit(buffer); | ||||||
|     while (S86_BufferIteratorHasMoreBytes(buffer_it)) { |     while (S86_BufferIteratorHasMoreBytes(buffer_it)) { | ||||||
| @ -326,7 +347,7 @@ int main(int argc, char **argv) | |||||||
|              instruction_type == S86_InstructionType_Count && instruction_index < S86_ARRAY_UCOUNT(S86_INSTRUCTIONS); |              instruction_type == S86_InstructionType_Count && instruction_index < S86_ARRAY_UCOUNT(S86_INSTRUCTIONS); | ||||||
|              instruction_index++) |              instruction_index++) | ||||||
|         { |         { | ||||||
|             S86_Instruction *item = S86_INSTRUCTIONS + instruction_index; |             S86_Instruction const *item = S86_INSTRUCTIONS + instruction_index; | ||||||
| 
 | 
 | ||||||
|             // NOTE: Check first instruction byte
 |             // NOTE: Check first instruction byte
 | ||||||
|             // =================================================================
 |             // =================================================================
 | ||||||
| @ -354,7 +375,9 @@ int main(int argc, char **argv) | |||||||
|         // =================================================================
 |         // =================================================================
 | ||||||
|         S86_ASSERT(op_code_size > 0 && op_code_size <= S86_ARRAY_UCOUNT(op_code_bytes)); |         S86_ASSERT(op_code_size > 0 && op_code_size <= S86_ARRAY_UCOUNT(op_code_bytes)); | ||||||
|         S86_ASSERT(instruction_type != S86_InstructionType_Count && "Unknown instruction"); |         S86_ASSERT(instruction_type != S86_InstructionType_Count && "Unknown instruction"); | ||||||
|  | 
 | ||||||
|         switch (instruction_type) { |         switch (instruction_type) { | ||||||
|  | 
 | ||||||
|             case S86_InstructionType_MOVRegOrMemToOrFromReg: { |             case S86_InstructionType_MOVRegOrMemToOrFromReg: { | ||||||
|                 // NOTE: Instruction does not have opcode bits in the 2nd byte
 |                 // NOTE: Instruction does not have opcode bits in the 2nd byte
 | ||||||
|                 S86_ASSERT(op_code_size == 1); |                 S86_ASSERT(op_code_size == 1); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user