Commit | Line | Data |
---|---|---|
93fac324 MM |
1 | /* This file is part of the program psim. |
2 | ||
3 | Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> | |
4 | ||
5 | This program 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 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program 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 this program; if not, write to the Free Software | |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | ||
19 | */ | |
20 | ||
21 | ||
22 | #ifndef _EMUL_BUGAPI_C_ | |
23 | #define _EMUL_BUGAPI_C_ | |
24 | ||
25 | ||
979c3c25 MM |
26 | /* from bug.S - Dale Rahn */ |
27 | #define _INCHR 0x00 | |
28 | #define _INSTAT 0x01 | |
29 | #define _INLN 0x02 | |
30 | #define _READSTR 0x03 | |
31 | #define _READLN 0x04 | |
32 | #define _OUTCHR 0x20 | |
33 | #define _OUTSTR 0x21 | |
34 | #define _OUTLN 0x22 | |
35 | #define _DSKRD 0x10 | |
36 | #define _DSKWR 0x11 | |
37 | #define _DSKCFIG 0x12 | |
38 | #define _DSKFMT 0x14 | |
39 | #define _DSKCTRL 0x15 | |
40 | #define _WRITE 0x23 | |
41 | #define _WRITELN 0x24 | |
42 | #define _DELAY 0x43 | |
43 | #define _RTC_RD 0x53 | |
44 | #define _RETURN 0x63 | |
45 | #define _BRD_ID 0x70 | |
46 | ||
93fac324 MM |
47 | /* Note: this module is called via a table. There is no benefit in |
48 | making it inline */ | |
49 | ||
50 | #include "emul_generic.h" | |
51 | #include "emul_bugapi.h" | |
52 | ||
53 | /* Any starting address less than this is assumed to be an OEA program | |
54 | rather than VEA. */ | |
55 | #ifndef OEA_START_ADDRESS | |
979c3c25 | 56 | #define OEA_START_ADDRESS 0x4000 |
93fac324 MM |
57 | #endif |
58 | ||
59 | #ifndef OEA_MEMORY_SIZE | |
60 | #define OEA_MEMORY_SIZE 0x100000 | |
61 | #endif | |
62 | ||
979c3c25 MM |
63 | /* All but CPU 0 are put into an infinate loop, this loop instruction |
64 | is stored at the address below */ | |
65 | #ifndef OEA_STALL_CPU_LOOP_ADDRESS | |
66 | #define OEA_STALL_CPU_LOOP_ADDRESS 0x00c10 | |
67 | #endif | |
68 | ||
69 | /* At initiallization, the system call exception branches to the BUG | |
70 | emulation code */ | |
71 | ||
72 | #ifndef OEA_SYSTEM_CALL_ADDRESS | |
73 | #define OEA_SYSTEM_CALL_ADDRESS 0x00c00 | |
74 | #endif | |
75 | ||
76 | ||
93fac324 MM |
77 | static os_emul_data * |
78 | emul_bugapi_create(device *root, | |
79 | bfd *image, | |
80 | const char *name) | |
81 | { | |
82 | ||
83 | /* check it really is for us */ | |
84 | if (name != NULL | |
979c3c25 MM |
85 | && strcmp(name, "bugapi") != 0 |
86 | && strcmp(name, "bug") != 0) | |
93fac324 MM |
87 | return NULL; |
88 | if (image != NULL | |
979c3c25 | 89 | && name == NULL |
93fac324 MM |
90 | && bfd_get_start_address(image) > OEA_START_ADDRESS) |
91 | return NULL; | |
92 | ||
93 | { | |
94 | ||
95 | const memory_size = OEA_MEMORY_SIZE; | |
96 | const elf_binary = (image != NULL | |
97 | && image->xvec->flavour == bfd_target_elf_flavour); | |
979c3c25 MM |
98 | #ifdef bfd_little_endian /* new bfd */ |
99 | const little_endian = (image != NULL && bfd_little_endian(image)); | |
100 | #else | |
101 | const little_endian = (image != NULL && | |
102 | !image->xvec->byteorder_big_p); | |
103 | #endif | |
93fac324 MM |
104 | |
105 | { /* options */ | |
106 | device *options = device_tree_add_found(root, "/", "options"); | |
107 | device_add_integer_property(options, | |
108 | "smp", | |
109 | MAX_NR_PROCESSORS); | |
110 | device_add_boolean_property(options, | |
111 | "little-endian?", | |
112 | little_endian); | |
113 | device_add_string_property(options, | |
114 | "env", | |
115 | "operating"); | |
116 | device_add_boolean_property(options, | |
117 | "strict-alignment?", | |
118 | (WITH_ALIGNMENT == STRICT_ALIGNMENT | |
979c3c25 | 119 | || little_endian)); |
93fac324 MM |
120 | device_add_boolean_property(options, |
121 | "floating-point?", | |
122 | WITH_FLOATING_POINT); | |
123 | device_add_string_property(options, | |
124 | "os-emul", | |
125 | "bugapi"); | |
126 | } | |
127 | ||
128 | /* hardware */ | |
129 | device_tree_add_found_uw_u_u(root, "/", "memory", | |
130 | 0, memory_size, access_read_write_exec); | |
131 | device_tree_add_found(root, "/", "iobus@0x400000"); | |
132 | device_tree_add_found(root, "/iobus", "console@0x000000,16"); | |
133 | device_tree_add_found(root, "/iobus", "halt@0x100000,4"); | |
134 | device_tree_add_found(root, "/iobus", "icu@0x200000,4"); | |
135 | ||
136 | { /* initialization */ | |
137 | device *init = device_tree_add_found(root, "/", "init"); | |
138 | { | |
139 | device *init_register = device_tree_add_found(init, "", "register"); | |
140 | device_add_integer_property(init_register, | |
141 | "pc", | |
979c3c25 MM |
142 | OEA_STALL_CPU_LOOP_ADDRESS); |
143 | device_add_integer_property(init_register, | |
144 | "0.pc", | |
145 | bfd_get_start_address(image)); | |
93fac324 MM |
146 | device_add_integer_property(init_register, |
147 | "sp", | |
148 | memory_size-16); | |
149 | device_add_integer_property(init_register, | |
150 | "msr", | |
979c3c25 MM |
151 | (msr_recoverable_interrupt |
152 | | (little_endian | |
153 | ? msr_little_endian_mode | |
154 | : 0) | |
155 | )); | |
156 | device_tree_add_found_uw_u_u(init, "", | |
157 | "data", | |
158 | OEA_SYSTEM_CALL_ADDRESS, | |
52edddb9 | 159 | 4, emul_call_instruction); |
979c3c25 MM |
160 | device_tree_add_found_uw_u_u(init, "", |
161 | "data", | |
162 | OEA_SYSTEM_CALL_ADDRESS + 4, | |
52edddb9 | 163 | 4, emul_rfi_instruction); |
979c3c25 MM |
164 | device_tree_add_found_uw_u_u(init, "", |
165 | "data", | |
166 | OEA_STALL_CPU_LOOP_ADDRESS, | |
52edddb9 | 167 | 4, emul_loop_instruction); |
93fac324 MM |
168 | } |
169 | { | |
170 | device *init_stack = device_tree_add_found(init, "", "stack"); | |
171 | device_add_null_property(init_stack, | |
172 | (elf_binary | |
173 | ? "elf" | |
174 | : "aix")); | |
175 | } | |
176 | { | |
177 | device *init_load_binary = device_tree_add_found(init, "", | |
178 | "load-binary"); | |
179 | device_add_null_property(init_load_binary, | |
180 | bfd_get_filename(image)); | |
181 | } | |
182 | } | |
183 | } | |
184 | ||
185 | return (os_emul_data*)-1; | |
186 | } | |
187 | ||
188 | static void | |
189 | emul_bugapi_init(os_emul_data *emul_data, | |
190 | int nr_cpus) | |
191 | { | |
192 | /* nothing happens here */ | |
193 | } | |
194 | ||
195 | static int | |
196 | emul_bugapi_instruction_call(cpu *processor, | |
197 | unsigned_word cia, | |
198 | unsigned_word ra, | |
199 | os_emul_data *emul_data) | |
200 | { | |
979c3c25 MM |
201 | const int call_id = cpu_registers(processor)->gpr[10]; |
202 | /* check that this isn't an invalid instruction */ | |
203 | if (cia != OEA_SYSTEM_CALL_ADDRESS) | |
204 | return 0; | |
205 | switch (call_id) { | |
206 | case _OUTCHR: | |
52edddb9 | 207 | printf_filtered("%c", (char)cpu_registers(processor)->gpr[3]); |
979c3c25 MM |
208 | break; |
209 | case _OUTLN: | |
210 | printf_filtered("\n"); | |
211 | break; | |
212 | case _RETURN: | |
213 | cpu_halt(processor, cia, was_exited, 0); /* always succeeds */ | |
214 | break; | |
215 | default: | |
216 | error("emul-bugapi: unimplemented bugapi call 0x%x from address 0x%lx\n", | |
217 | call_id, SRR0); | |
218 | break; | |
219 | } | |
93fac324 | 220 | return 1; |
979c3c25 MM |
221 | /* the instruction following this one is a RFI. Thus by just |
222 | continuing the return from system call is performed */ | |
93fac324 MM |
223 | } |
224 | ||
225 | const os_emul emul_bugapi = { | |
226 | "bugapi", | |
227 | emul_bugapi_create, | |
228 | emul_bugapi_init, | |
229 | 0, /*system_call*/ | |
230 | emul_bugapi_instruction_call, | |
231 | 0 /*data*/ | |
232 | }; | |
233 | ||
234 | #endif |