OpenCores
URL https://opencores.org/ocsvn/s80186/s80186/trunk

Subversion Repositories s80186

[/] [s80186/] [trunk/] [sim/] [cppmodel/] [ModRM.cpp] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
// Copyright Jamie Iles, 2017
2
//
3
// This file is part of s80x86.
4
//
5
// s80x86 is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// s80x86 is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with s80x86.  If not, see <http://www.gnu.org/licenses/>.
17
 
18
#include "ModRM.h"
19
 
20
#include <cassert>
21
 
22
ModRMDecoder::ModRMDecoder(std::function<uint8_t()> get_byte,
23
                           const RegisterFile *registers)
24
    : get_byte(get_byte), registers(registers), width(OP_WIDTH_16), modrm(0)
25
{
26
}
27
 
28
void ModRMDecoder::clear()
29
{
30
    is_decoded = false;
31
}
32
 
33
void ModRMDecoder::decode()
34
{
35
    is_decoded = true;
36
    modrm = get_byte();
37
    // Cache the address now, we need to process all mod/rm bytes +
38
    // displacements before the opcode handler starts reading immediates etc.
39
    addr_is_cached = false;
40
    if (rm_type() == OP_MEM)
41
        effective_address();
42
}
43
 
44
OperandType ModRMDecoder::rm_type() const
45
{
46
    assert(is_decoded);
47
    return (modrm & 0xc0) == 0xc0 ? OP_REG : OP_MEM;
48
}
49
 
50
void ModRMDecoder::set_width(OperandWidth width)
51
{
52
    this->width = width;
53
}
54
 
55
GPR ModRMDecoder::reg() const
56
{
57
    assert(is_decoded);
58
    auto reg = raw_reg();
59
 
60
    if (width == OP_WIDTH_8)
61
        return static_cast<GPR>(static_cast<int>(AL) + reg);
62
 
63
    return static_cast<GPR>(static_cast<int>(AX) + reg);
64
}
65
 
66
int ModRMDecoder::raw_reg() const
67
{
68
    assert(is_decoded);
69
    return (modrm >> 3) & 0x7;
70
}
71
 
72
GPR ModRMDecoder::rm_reg() const
73
{
74
    assert(is_decoded);
75
    assert(rm_type() == OP_REG);
76
 
77
    int reg = (modrm >> 0) & 0x7;
78
 
79
    if (width == OP_WIDTH_8)
80
        return static_cast<GPR>(static_cast<int>(AL) + reg);
81
 
82
    return static_cast<GPR>(static_cast<int>(AX) + reg);
83
}
84
 
85
uint16_t ModRMDecoder::effective_address()
86
{
87
    assert(is_decoded);
88
    if (addr_is_cached)
89
        return cached_address;
90
 
91
    cached_address = calculate_effective_address();
92
    addr_is_cached = true;
93
 
94
    return cached_address;
95
}
96
 
97
uint16_t ModRMDecoder::calculate_effective_address()
98
{
99
    assert(rm_type() == OP_MEM);
100
    assert(modrm >> 6 != 0x03);
101
 
102
    switch ((modrm >> 6) & 0x3) {
103
    case 0x00: return mod00();
104
    case 0x01: return mod01();
105
    case 0x02: return mod10();
106
    }
107
 
108
    __builtin_unreachable();
109
}
110
 
111
uint16_t ModRMDecoder::mod00()
112
{
113
    switch (modrm & 0x7) {
114
    case 0x0: return registers->get(BX) + registers->get(SI);
115
    case 0x1: return registers->get(BX) + registers->get(DI);
116
    case 0x2: return registers->get(BP) + registers->get(SI);
117
    case 0x3: return registers->get(BP) + registers->get(DI);
118
    case 0x4: return registers->get(SI);
119
    case 0x5: return registers->get(DI);
120
    case 0x6:
121
        return static_cast<uint16_t>(get_byte()) |
122
               (static_cast<uint16_t>(get_byte()) << 8);
123
    case 0x7: return registers->get(BX);
124
    }
125
    __builtin_unreachable();
126
}
127
 
128
uint16_t ModRMDecoder::mod01()
129
{
130
    auto displacement = static_cast<int8_t>(get_byte());
131
    switch (modrm & 0x7) {
132
    case 0x0: return registers->get(BX) + registers->get(SI) + displacement;
133
    case 0x1: return registers->get(BX) + registers->get(DI) + displacement;
134
    case 0x2: return registers->get(BP) + registers->get(SI) + displacement;
135
    case 0x3: return registers->get(BP) + registers->get(DI) + displacement;
136
    case 0x4: return registers->get(SI) + displacement;
137
    case 0x5: return registers->get(DI) + displacement;
138
    case 0x6: return registers->get(BP) + displacement;
139
    case 0x7: return registers->get(BX) + displacement;
140
    }
141
    __builtin_unreachable();
142
}
143
 
144
uint16_t ModRMDecoder::mod10()
145
{
146
    auto displacement = static_cast<int16_t>(get_byte()) |
147
                        (static_cast<uint16_t>(get_byte()) << 8);
148
    switch (modrm & 0x7) {
149
    case 0x0: return registers->get(BX) + registers->get(SI) + displacement;
150
    case 0x1: return registers->get(BX) + registers->get(DI) + displacement;
151
    case 0x2: return registers->get(BP) + registers->get(SI) + displacement;
152
    case 0x3: return registers->get(BP) + registers->get(DI) + displacement;
153
    case 0x4: return registers->get(SI) + displacement;
154
    case 0x5: return registers->get(DI) + displacement;
155
    case 0x6: return registers->get(BP) + displacement;
156
    case 0x7: return registers->get(BX) + displacement;
157
    }
158
    __builtin_unreachable();
159
}
160
 
161
bool ModRMDecoder::uses_bp_as_base() const
162
{
163
    if (!is_decoded)
164
        return false;
165
 
166
    if (rm_type() != OP_MEM)
167
        return false;
168
 
169
    auto mod = modrm >> 6;
170
    auto rm = modrm & 0x7;
171
 
172
    if (mod == 0)
173
        return rm == 0x2 || rm == 0x3;
174
 
175
    return rm == 0x2 || rm == 0x3 || rm == 0x6;
176
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.