From 1cd86c0cdb349cd6043dd72b580e233a7811d72d Mon Sep 17 00:00:00 2001 From: doyle Date: Sat, 18 Mar 2023 23:37:22 +1100 Subject: [PATCH] perfaware/part1: Add support for in/out" --- part1/sim8086.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/part1/sim8086.c b/part1/sim8086.c index eb86f2e..98a3a93 100644 --- a/part1/sim8086.c +++ b/part1/sim8086.c @@ -88,6 +88,12 @@ typedef enum S86_InstructionType { S86_InstructionType_XCHGRegOrMemWithReg, S86_InstructionType_XCHGRegWithAccum, + S86_InstructionType_INFixedPort, + S86_InstructionType_INVariablePort, + + S86_InstructionType_OUTFixedPort, + S86_InstructionType_OUTVariablePort, + S86_InstructionType_ADDRegOrMemToOrFromReg, S86_InstructionType_ADDImmediateToRegOrMem, S86_InstructionType_ADDImmediateToAccum, @@ -456,6 +462,16 @@ int main(int argc, char **argv) [S86_InstructionType_XCHGRegWithAccum] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, .op_bits0 = 0b1001'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("xchg")}, + [S86_InstructionType_INFixedPort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("in")}, + [S86_InstructionType_INVariablePort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("in")}, + + [S86_InstructionType_OUTFixedPort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("out")}, + [S86_InstructionType_OUTVariablePort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("out")}, + [S86_InstructionType_ADDRegOrMemToOrFromReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, .op_bits0 = 0b0000'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("add")}, [S86_InstructionType_ADDImmediateToRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, @@ -752,6 +768,33 @@ int main(int argc, char **argv) S86_PrintLnFmt("%.*s ax, %.*s", S86_STR8_FMT(instruction->mnemonic), S86_STR8_FMT(reg_name)); } break; + case S86_InstructionType_INFixedPort: /*FALLTHRU*/ + case S86_InstructionType_INVariablePort: /*FALLTHRU*/ + case S86_InstructionType_OUTFixedPort: /*FALLTHRU*/ + case S86_InstructionType_OUTVariablePort: { + S86_ASSERT(op_code_size == 1); + uint8_t w = (op_code_bytes[0] & 0b0000'0001) >> 0; + S86_Str8 accum_name = w ? S86_STR8("ax") : S86_STR8("al"); + bool is_in = instruction_type == S86_InstructionType_INFixedPort || + instruction_type == S86_InstructionType_INVariablePort; + + char data_val[8] = {0}; + if (instruction_type == S86_InstructionType_INFixedPort || + instruction_type == S86_InstructionType_OUTFixedPort) { + uint8_t data = S86_BufferIteratorNextByte(&buffer_it); + snprintf(data_val, sizeof(data_val), "%d", data); + } else { + data_val[0] = 'd'; + data_val[1] = 'x'; + } + + S86_PrintFmt("%.*s ", S86_STR8_FMT(instruction->mnemonic)); + if (is_in) + S86_PrintLnFmt("%.*s, %s", S86_STR8_FMT(accum_name), data_val); + else + S86_PrintLnFmt("%s, %.*s", data_val, S86_STR8_FMT(accum_name)); + } break; + case S86_InstructionType_MOVAccumToMem: /*FALLTHRU*/ case S86_InstructionType_MOVMemToAccum: { S86_ASSERT(op_code_size == 1);