Implement one immediate label reference operand
All checks were successful
Validate the build / validate-build (push) Successful in 43s
All checks were successful
Validate the build / validate-build (push) Successful in 43s
Also adds opcode data for jmp and call
This commit is contained in:
parent
c848995ad6
commit
7cefc3564d
@ -138,8 +138,128 @@ opcode_data_t *const opcodes[] = {
|
|||||||
{ .kind = OPERAND_REGISTER, .size = OPERAND_SIZE_64 },
|
{ .kind = OPERAND_REGISTER, .size = OPERAND_SIZE_64 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// CALL rel32
|
||||||
|
&(opcode_data_t) {
|
||||||
|
.mnemonic = "call",
|
||||||
|
.opcode = 0xE8,
|
||||||
|
.opcode_extension = opcode_extension_none,
|
||||||
|
.encoding_class = ENCODING_DEFAULT,
|
||||||
|
.operand_count = 1,
|
||||||
|
.operands = {
|
||||||
|
{ .kind = OPERAND_IMMEDIATE, .size = OPERAND_SIZE_32 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// CALL reg64
|
||||||
|
&(opcode_data_t) {
|
||||||
|
.mnemonic = "call",
|
||||||
|
.opcode = 0xFF,
|
||||||
|
.opcode_extension = 2,
|
||||||
|
.encoding_class = ENCODING_DEFAULT,
|
||||||
|
.rex_w_prefix = true,
|
||||||
|
.operand_count = 1,
|
||||||
|
.operands = {
|
||||||
|
{ .kind = OPERAND_REGISTER, .size = OPERAND_SIZE_64 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// CALL mem64
|
||||||
|
&(opcode_data_t) {
|
||||||
|
.mnemonic = "call",
|
||||||
|
.opcode = 0xFF,
|
||||||
|
.opcode_extension = 2,
|
||||||
|
.encoding_class = ENCODING_DEFAULT,
|
||||||
|
.rex_w_prefix = true,
|
||||||
|
.operand_count = 1,
|
||||||
|
.operands = {
|
||||||
|
{ .kind = OPERAND_MEMORY, .size = OPERAND_SIZE_64 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// JMP rel8 (short jump)
|
||||||
|
&(opcode_data_t) {
|
||||||
|
.mnemonic = "jmp",
|
||||||
|
.opcode = 0xEB,
|
||||||
|
.opcode_extension = opcode_extension_none,
|
||||||
|
.encoding_class = ENCODING_DEFAULT,
|
||||||
|
.operand_count = 1,
|
||||||
|
.operands = {
|
||||||
|
{ .kind = OPERAND_IMMEDIATE, .size = OPERAND_SIZE_8 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// JMP rel16
|
||||||
|
&(opcode_data_t) {
|
||||||
|
.mnemonic = "jmp",
|
||||||
|
.opcode = 0xE9,
|
||||||
|
.opcode_extension = opcode_extension_none,
|
||||||
|
.encoding_class = ENCODING_DEFAULT,
|
||||||
|
.operand_size_prefix = true,
|
||||||
|
.operand_count = 1,
|
||||||
|
.operands = {
|
||||||
|
{ .kind = OPERAND_IMMEDIATE, .size = OPERAND_SIZE_16 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// JMP reg16
|
||||||
|
&(opcode_data_t) {
|
||||||
|
.mnemonic = "jmp",
|
||||||
|
.opcode = 0xFF,
|
||||||
|
.opcode_extension = 4,
|
||||||
|
.encoding_class = ENCODING_DEFAULT,
|
||||||
|
.operand_size_prefix = true,
|
||||||
|
.operand_count = 1,
|
||||||
|
.operands = {
|
||||||
|
{ .kind = OPERAND_REGISTER, .size = OPERAND_SIZE_16 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// JMP rel32 (near jump)
|
||||||
|
&(opcode_data_t) {
|
||||||
|
.mnemonic = "jmp",
|
||||||
|
.opcode = 0xE9,
|
||||||
|
.opcode_extension = opcode_extension_none,
|
||||||
|
.encoding_class = ENCODING_DEFAULT,
|
||||||
|
.operand_count = 1,
|
||||||
|
.operands = {
|
||||||
|
{ .kind = OPERAND_IMMEDIATE, .size = OPERAND_SIZE_32 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// JMP reg32
|
||||||
|
&(opcode_data_t) {
|
||||||
|
.mnemonic = "jmp",
|
||||||
|
.opcode = 0xFF,
|
||||||
|
.opcode_extension = 4,
|
||||||
|
.encoding_class = ENCODING_DEFAULT,
|
||||||
|
.operand_count = 1,
|
||||||
|
.operands = {
|
||||||
|
{ .kind = OPERAND_REGISTER, .size = OPERAND_SIZE_32 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// JMP reg64
|
||||||
|
&(opcode_data_t) {
|
||||||
|
.mnemonic = "jmp",
|
||||||
|
.opcode = 0xFF,
|
||||||
|
.opcode_extension = 4,
|
||||||
|
.encoding_class = ENCODING_DEFAULT,
|
||||||
|
.rex_w_prefix = true,
|
||||||
|
.operand_count = 1,
|
||||||
|
.operands = {
|
||||||
|
{ .kind = OPERAND_REGISTER, .size = OPERAND_SIZE_64 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// JMP mem64
|
||||||
|
&(opcode_data_t) {
|
||||||
|
.mnemonic = "jmp",
|
||||||
|
.opcode = 0xFF,
|
||||||
|
.opcode_extension = 4,
|
||||||
|
.encoding_class = ENCODING_DEFAULT,
|
||||||
|
.rex_w_prefix = true,
|
||||||
|
.operand_count = 1,
|
||||||
|
.operands = {
|
||||||
|
{ .kind = OPERAND_MEMORY, .size = OPERAND_SIZE_64 },
|
||||||
|
},
|
||||||
|
},
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -279,12 +279,9 @@ bool is_operand_match(operand_info_t *info, ast_node_t *operand) {
|
|||||||
|
|
||||||
if (child->id == NODE_NUMBER)
|
if (child->id == NODE_NUMBER)
|
||||||
return (ast_node_number_value(child)->size & info->size) > 0;
|
return (ast_node_number_value(child)->size & info->size) > 0;
|
||||||
else if (child->id == NODE_LABEL_REFERENCE)
|
else if (child->id == NODE_LABEL_REFERENCE) {
|
||||||
return info->size == OPERAND_SIZE_32;
|
return info->size &= ast_node_reference_value(child)->size;
|
||||||
// FIXME: first pass should give us information about the distance of
|
}
|
||||||
// the label reference so we can pick a size more appropriately instead
|
|
||||||
// of just defaulting to 32 bits
|
|
||||||
break;
|
|
||||||
} // end OPERAND_IMMEDIATE case
|
} // end OPERAND_IMMEDIATE case
|
||||||
}
|
}
|
||||||
assert(false && "unreachable");
|
assert(false && "unreachable");
|
||||||
@ -389,9 +386,9 @@ error_t *encode_one_immediate(encoder_t *encoder, opcode_data_t *opcode,
|
|||||||
assert(immediate->id == NODE_NUMBER ||
|
assert(immediate->id == NODE_NUMBER ||
|
||||||
immediate->id == NODE_LABEL_REFERENCE);
|
immediate->id == NODE_LABEL_REFERENCE);
|
||||||
|
|
||||||
|
operand_size_t size = opcode->operands[0].size;
|
||||||
if (immediate->id == NODE_NUMBER) {
|
if (immediate->id == NODE_NUMBER) {
|
||||||
uint64_t value = ast_node_number_value(immediate)->value;
|
uint64_t value = ast_node_number_value(immediate)->value;
|
||||||
operand_size_t size = opcode->operands[0].size;
|
|
||||||
error_t *err = nullptr;
|
error_t *err = nullptr;
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case OPERAND_SIZE_8:
|
case OPERAND_SIZE_8:
|
||||||
@ -411,10 +408,21 @@ error_t *encode_one_immediate(encoder_t *encoder, opcode_data_t *opcode,
|
|||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
} else {
|
} else {
|
||||||
// FIXME: this still assumes references are always 32 bit
|
reference_t *reference = ast_node_reference_value(immediate);
|
||||||
uint32_t value = 0xDEADBEEF;
|
switch (size) {
|
||||||
return bytes_append_uint32(encoding, value);
|
case OPERAND_SIZE_64:
|
||||||
|
return bytes_append_uint64(encoding, reference->address);
|
||||||
|
case OPERAND_SIZE_32:
|
||||||
|
return bytes_append_uint32(encoding, reference->offset);
|
||||||
|
case OPERAND_SIZE_16:
|
||||||
|
return bytes_append_uint16(encoding, reference->offset);
|
||||||
|
case OPERAND_SIZE_8:
|
||||||
|
return bytes_append_uint8(encoding, reference->offset);
|
||||||
|
default:
|
||||||
|
assert(false && "intentionally unhandled");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t *encode_one_memory(encoder_t *encoder, opcode_data_t *opcode,
|
error_t *encode_one_memory(encoder_t *encoder, opcode_data_t *opcode,
|
||||||
@ -603,6 +611,13 @@ error_t *encoder_collect_reference_info(encoder_t *encoder, ast_node_t *node,
|
|||||||
node->value.reference.size = size;
|
node->value.reference.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < node->len; ++i) {
|
||||||
|
error_t *err = encoder_collect_reference_info(
|
||||||
|
encoder, node->children[i], statement);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user