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

Subversion Repositories s80186

[/] [s80186/] [trunk/] [sim/] [cppmodel/] [instructions/] [div.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
// div r/m, 8-bit
19
void EmulatorPimpl::divf6()
20
{
21
    auto divisor = read_data<uint8_t>();
22
    auto dividend = registers->get(AX);
23
 
24
    if (divisor == 0 || ((dividend / divisor) & 0xff00)) {
25
        auto flags = registers->get_flags();
26
        push_word(flags);
27
        push_word(registers->get(CS));
28
        push_word(registers->get(IP));
29
 
30
        flags &= ~(IF | TF);
31
        registers->set_flags(flags, IF | TF);
32
 
33
        auto new_cs = mem->read<uint16_t>(VEC_DIVIDE_ERROR + 2);
34
        auto new_ip = mem->read<uint16_t>(VEC_DIVIDE_ERROR + 0);
35
 
36
        registers->set(CS, new_cs);
37
        registers->set(IP, new_ip);
38
        jump_taken = true;
39
 
40
        return;
41
    }
42
 
43
    uint8_t quotient = dividend / divisor;
44
    uint8_t remainder = dividend % divisor;
45
 
46
    registers->set(AH, remainder);
47
    registers->set(AL, quotient);
48
}
49
 
50
// div r/m, 16-bit
51
void EmulatorPimpl::divf7()
52
{
53
    auto divisor = read_data<uint16_t>();
54
    uint32_t dividend =
55
        (static_cast<uint32_t>(registers->get(DX)) << 16) | registers->get(AX);
56
 
57
    if (divisor == 0 || ((dividend / divisor) & 0xffff0000)) {
58
        auto flags = registers->get_flags();
59
        push_word(flags);
60
        push_word(registers->get(CS));
61
        push_word(registers->get(IP));
62
 
63
        flags &= ~(IF | TF);
64
        registers->set_flags(flags, IF | TF);
65
 
66
        auto new_cs = mem->read<uint16_t>(VEC_DIVIDE_ERROR + 2);
67
        auto new_ip = mem->read<uint16_t>(VEC_DIVIDE_ERROR + 0);
68
 
69
        registers->set(CS, new_cs);
70
        registers->set(IP, new_ip);
71
        jump_taken = true;
72
 
73
        return;
74
    }
75
 
76
    uint16_t quotient = dividend / divisor;
77
    uint16_t remainder = dividend % divisor;
78
 
79
    registers->set(DX, remainder);
80
    registers->set(AX, quotient);
81
}
82
 
83
// idiv r/m, 8-bit
84
void EmulatorPimpl::idivf6()
85
{
86
    int8_t divisor = static_cast<int8_t>(read_data<uint8_t>());
87
    int16_t dividend = static_cast<int16_t>(registers->get(AX));
88
 
89
    if (divisor == 0 || (dividend / divisor < -128) ||
90
        (dividend / divisor > 127)) {
91
        auto flags = registers->get_flags();
92
        push_word(flags);
93
        push_word(registers->get(CS));
94
        push_word(registers->get(IP));
95
 
96
        flags &= ~(IF | TF);
97
        registers->set_flags(flags, IF | TF);
98
 
99
        auto new_cs = mem->read<uint16_t>(VEC_DIVIDE_ERROR + 2);
100
        auto new_ip = mem->read<uint16_t>(VEC_DIVIDE_ERROR + 0);
101
 
102
        registers->set(CS, new_cs);
103
        registers->set(IP, new_ip);
104
        jump_taken = true;
105
 
106
        return;
107
    }
108
 
109
    int8_t quotient = dividend / divisor;
110
    int8_t remainder = dividend % divisor;
111
 
112
    registers->set(AH, remainder);
113
    registers->set(AL, quotient);
114
}
115
 
116
// div r/m, 16-bit
117
void EmulatorPimpl::idivf7()
118
{
119
    auto divisor = static_cast<int16_t>(read_data<uint16_t>());
120
    int32_t dividend =
121
        (static_cast<uint32_t>(registers->get(DX)) << 16) | registers->get(AX);
122
 
123
    if (divisor == 0 || (dividend / divisor < -32768) ||
124
        (dividend / divisor) > 32767) {
125
        auto flags = registers->get_flags();
126
        push_word(flags);
127
        push_word(registers->get(CS));
128
        push_word(registers->get(IP));
129
 
130
        flags &= ~(IF | TF);
131
        registers->set_flags(flags, IF | TF);
132
 
133
        auto new_cs = mem->read<uint16_t>(VEC_DIVIDE_ERROR + 2);
134
        auto new_ip = mem->read<uint16_t>(VEC_DIVIDE_ERROR + 0);
135
 
136
        registers->set(CS, new_cs);
137
        registers->set(IP, new_ip);
138
        jump_taken = true;
139
 
140
        return;
141
    }
142
 
143
    int16_t quotient = dividend / divisor;
144
    int16_t remainder = dividend % divisor;
145
 
146
    registers->set(DX, remainder);
147
    registers->set(AX, quotient);
148
}

powered by: WebSVN 2.1.0

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