diff options
author | Kartik Agaram <vc@akkartik.com> | 2019-03-17 22:57:42 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2019-03-17 22:57:42 -0700 |
commit | 938185b33ccf30aa8aa20bf8cc22073e140697bf (patch) | |
tree | 4e65589bca1a5145ec8056afba49aae8d9499f75 /subx | |
parent | ba80524a9f38667f9d82990067192103b490dd73 (diff) | |
download | mu-938185b33ccf30aa8aa20bf8cc22073e140697bf.tar.gz |
5008
Diffstat (limited to 'subx')
-rw-r--r-- | subx/030---operands.cc | 1 | ||||
-rw-r--r-- | subx/032check_operand_bounds.cc | 88 | ||||
-rw-r--r-- | subx/035labels.cc | 8 |
3 files changed, 91 insertions, 6 deletions
diff --git a/subx/030---operands.cc b/subx/030---operands.cc index c8e2942d..1a4ec563 100644 --- a/subx/030---operands.cc +++ b/subx/030---operands.cc @@ -138,6 +138,7 @@ void init_operand_type_help() { ); put(Help, "disp16", "16-bit value to be added in many instructions.\n" + "Currently not used in any SubX instructions.\n" ); put(Help, "disp32", "32-bit value to be added in many instructions.\n" diff --git a/subx/032check_operand_bounds.cc b/subx/032check_operand_bounds.cc index ca114e22..0aae0f67 100644 --- a/subx/032check_operand_bounds.cc +++ b/subx/032check_operand_bounds.cc @@ -47,8 +47,14 @@ void check_operand_bounds(const word& w) { if (!looks_like_hex_int(w.data)) continue; // later transforms are on their own to do their own bounds checking int32_t x = parse_int(w.data); if (x >= 0) { - if (static_cast<uint32_t>(x) >= p->second) - raise << "'" << w.original << "' too large to fit in bitfield " << p->first << '\n' << end(); + if (p->first == "disp8" || p->first == "disp16") { + if (static_cast<uint32_t>(x) >= p->second/2) + raise << "'" << w.original << "' too large to fit in signed bitfield " << p->first << '\n' << end(); + } + else { + if (static_cast<uint32_t>(x) >= p->second) + raise << "'" << w.original << "' too large to fit in bitfield " << p->first << '\n' << end(); + } } else { // hacky? assuming bound is a power of 2 @@ -57,3 +63,81 @@ void check_operand_bounds(const word& w) { } } } + +void test_check_bitfield_sizes_for_imm8() { + run( + "== 0x1\n" // code segment + "c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX 0xff/imm8" // shift EBX left + ); + CHECK(!trace_contains_errors()); +} + +void test_check_bitfield_sizes_for_imm8_error() { + Hide_errors = true; + run( + "== 0x1\n" // code segment + "c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX 0x100/imm8" // shift EBX left + ); + CHECK_TRACE_CONTENTS( + "error: '0x100/imm8' too large to fit in bitfield imm8\n" + ); +} + +void test_check_bitfield_sizes_for_negative_imm8() { + run( + "== 0x1\n" // code segment + "c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX -0x80/imm8" // shift EBX left + ); + CHECK(!trace_contains_errors()); +} + +void test_check_bitfield_sizes_for_negative_imm8_error() { + Hide_errors = true; + run( + "== 0x1\n" // code segment + "c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX -0x81/imm8" // shift EBX left + ); + CHECK_TRACE_CONTENTS( + "error: '-0x81/imm8' too large to fit in bitfield imm8\n" + ); +} + +void test_check_bitfield_sizes_for_disp8() { + // not bothering to run + transform( + "== 0x1\n" // code segment + "01/add 1/mod/*+disp8 3/rm32 1/r32 0x7f/disp8\n" // add ECX to *(EBX+0x7f) + ); + CHECK(!trace_contains_errors()); +} + +void test_check_bitfield_sizes_for_disp8_error() { + Hide_errors = true; + run( + "== 0x1\n" // code segment + "01/add 1/mod/*+disp8 3/rm32 1/r32 0x80/disp8\n" // add ECX to *(EBX+0x80) + ); + CHECK_TRACE_CONTENTS( + "error: '0x80/disp8' too large to fit in signed bitfield disp8\n" + ); +} + +void test_check_bitfield_sizes_for_negative_disp8() { + // not bothering to run + transform( + "== 0x1\n" // code segment + "01/add 1/mod/*+disp8 3/rm32 1/r32 -0x80/disp8\n" // add ECX to *(EBX-0x80) + ); + CHECK(!trace_contains_errors()); +} + +void test_check_bitfield_sizes_for_negative_disp8_error() { + Hide_errors = true; + run( + "== 0x1\n" // code segment + "01/add 1/mod/*+disp8 3/rm32 1/r32 -0x81/disp8\n" // add ECX to *(EBX-0x81) + ); + CHECK_TRACE_CONTENTS( + "error: '-0x81/disp8' too large to fit in bitfield disp8\n" + ); +} diff --git a/subx/035labels.cc b/subx/035labels.cc index 322d1952..575bcec2 100644 --- a/subx/035labels.cc +++ b/subx/035labels.cc @@ -222,14 +222,14 @@ void replace_labels_with_displacements(segment& code, const map<string, int32_t> if (contains_key(byte_index, curr.data)) { int32_t displacement = static_cast<int32_t>(get(byte_index, curr.data)) - byte_index_next_instruction_starts_at; if (has_operand_metadata(curr, "disp8")) { - if (displacement > 0xff || displacement < -0x7f) - raise << "'" << to_string(inst) << "': label too far away for displacement " << std::hex << displacement << " to fit in 8 bits\n" << end(); + if (displacement > 0x7f || displacement < -0x7f) + raise << "'" << to_string(inst) << "': label too far away for displacement " << std::hex << displacement << " to fit in 8 signed bits\n" << end(); else emit_hex_bytes(new_inst, displacement, 1); } else if (has_operand_metadata(curr, "disp16")) { - if (displacement > 0xffff || displacement < -0x7fff) - raise << "'" << to_string(inst) << "': label too far away for displacement " << std::hex << displacement << " to fit in 16 bits\n" << end(); + if (displacement > 0x7fff || displacement < -0x7fff) + raise << "'" << to_string(inst) << "': label too far away for displacement " << std::hex << displacement << " to fit in 16 signed bits\n" << end(); else emit_hex_bytes(new_inst, displacement, 2); } |