1 /* Base class for devices that are memory-mapped into the CPU's
2    address space.
3    Copyright 2001, 2003 Brian R. Gaeke.
4    Copyright 2002 Paul Twohey.
5 
6 This file is part of VMIPS.
7 
8 VMIPS is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2 of the License, or (at your
11 option) any later version.
12 
13 VMIPS is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License along
19 with VMIPS; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
21 
22 /* Routines implementing memory mappings for devices which support
23  * memory-mapped I/O. */
24 
25 #include "accesstypes.h"
26 #include "range.h"
27 #include "devicemap.h"
28 #include "cpu.h"
29 #include "vmips.h"
30 #include "mapper.h"
31 #include <cstdlib>
32 
33 uint16
fetch_halfword(uint32 offset,DeviceExc * client)34 DeviceMap::fetch_halfword(uint32 offset, DeviceExc *client)
35 {
36     uint32 word_data = fetch_word(offset & ~0x03, DATALOAD, client);
37     word_data = machine->physmem->host_to_mips_word(word_data);
38     uint32 halfword_offset_in_word = ((offset & 0x02) >> 1);
39     if (!machine->cpu->is_bigendian()) {
40 	halfword_offset_in_word = 1 - halfword_offset_in_word;
41     }
42     uint16 rv;
43     switch (halfword_offset_in_word) {
44 	case 0: rv = (word_data >> 16) & 0xffff; break;
45 	case 1: rv = word_data & 0xffff; break;
46 	default: abort();
47     }
48     rv = machine->physmem->mips_to_host_halfword(rv);
49     return rv;
50 }
51 
52 uint8
fetch_byte(uint32 offset,DeviceExc * client)53 DeviceMap::fetch_byte(uint32 offset, DeviceExc *client)
54 {
55     uint32 word_data = fetch_word(offset & ~0x03, DATALOAD, client);
56     word_data = machine->physmem->host_to_mips_word(word_data);
57     uint32 byte_offset_in_word = (offset & 0x03);
58     if (!machine->cpu->is_bigendian()) {
59 	byte_offset_in_word = 3 - byte_offset_in_word;
60     }
61     uint8 rv;
62     switch (byte_offset_in_word) {
63 	case 0: rv = (word_data >> 24) & 0xff; break;
64 	case 1: rv = (word_data >> 16) & 0xff; break;
65 	case 2: rv = (word_data >> 8) & 0xff; break;
66 	case 3: rv = word_data & 0xff; break;
67 	default: abort();
68     }
69     return rv;
70 }
71 
72 void
store_halfword(uint32 offset,uint16 data,DeviceExc * client)73 DeviceMap::store_halfword(uint32 offset, uint16 data, DeviceExc *client)
74 {
75     const uint32 word_offset = offset & 0xfffffffc;
76     uint32 halfword_offset_in_word = ((offset & 0x02) >> 1);
77     uint32 word_data = 0;
78     if (!machine->cpu->is_bigendian()) {
79 	halfword_offset_in_word = 1 - halfword_offset_in_word;
80     }
81     data = machine->physmem->host_to_mips_halfword(data);
82     switch (halfword_offset_in_word) {
83 	case 0: word_data = (data << 16) & 0xffff0000; break;
84 	case 1: word_data = data & 0x0000ffff; break;
85 	default: abort();
86     }
87     word_data = machine->physmem->mips_to_host_word(word_data);
88     store_word(word_offset, word_data, client);
89 }
90 
91 void
store_byte(uint32 offset,uint8 data,DeviceExc * client)92 DeviceMap::store_byte(uint32 offset, uint8 data, DeviceExc *client)
93 {
94     const uint32 word_offset = offset & 0xfffffffc;
95     uint32 byte_offset_in_word = (offset & 0x03);
96     uint32 word_data = 0;
97     if (!machine->cpu->is_bigendian()) {
98 	byte_offset_in_word = 3 - byte_offset_in_word;
99     }
100     switch (byte_offset_in_word) {
101 	case 0: word_data = (data << 24) & 0xff000000; break;
102 	case 1: word_data = (data << 16) & 0x00ff0000; break;
103 	case 2: word_data = (data << 8) & 0x0000ff00; break;
104 	case 3: word_data = data & 0x000000ff; break;
105 	default: abort();
106     }
107     word_data = machine->physmem->mips_to_host_word(word_data);
108     store_word(word_offset, word_data, client);
109 }
110 
111 bool
canRead(uint32 offset)112 DeviceMap::canRead(uint32 offset)
113 {
114     return true;
115 }
116 
117 bool
canWrite(uint32 offset)118 DeviceMap::canWrite(uint32 offset)
119 {
120     return true;
121 }
122