1 // mips.cxx - MIPS monitors (IDT, PMON, ...). -*- C++ -*-
3 // Copyright (C) 1999, 2000 Red Hat.
4 // This file is part of SID and is licensed under the GPL.
5 // See the file COPYING.SID for conditions for redistribution.
7 // ??? At present this is very minimal. Enough to get the simulator going.
8 // Cadillac version left for later.
16 using namespace sidutil;
18 mips32_idt::mips32_idt()
20 // so we can query how big it is
21 add_uni_relation("ram", &this->ram);
22 // so we can stuff in our monitor implementation
23 add_uni_relation("rom", &this->rom);
25 this->register_attribute_names[-1] = "r0"; // result
26 this->register_attribute_names[-2] = "r0"; // error
27 this->register_attribute_names[0] = "r3"; // function code
28 this->register_attribute_names[1] = "r4"; // arg 1
29 this->register_attribute_names[2] = "r5"; // arg 2
30 this->register_attribute_names[3] = "r6"; // arg 3
33 // For the idt monitor we need to fill the rom with suitable contents.
40 // Fill the ROM with suitable code.
42 int32 syscall_insn = 0x0000000c;
43 int32 return_insn = 0x03e00008;
44 sid::bus* memory = this->rom->find_bus ("read-write-port");
48 for (int i = 0; i < SYSCALL_MAX; ++i, addr += 8)
50 int32 insn = syscall_insn | ((i + SYSCALL_MIN) << 6);
52 if (this->endian == sidutil::endian_little)
54 little_int_4 little_insn = insn;
55 little_int_4 little_return_insn = return_insn;
56 bus::status s = memory->write(addr, little_return_insn);
57 assert (s == bus::ok);
58 // Execute the syscall in the delay slot.
59 s = memory->write(addr + 4, little_insn);
60 assert (s == bus::ok);
64 big_int_4 big_insn = insn;
65 big_int_4 big_return_insn = return_insn;
66 bus::status s = memory->write(addr, big_return_insn);
67 assert (s == bus::ok);
68 // Execute the syscall in the delay slot.
69 s = memory->write(addr + 4, big_insn);
70 assert (s == bus::ok);
76 mips32_idt::get_int_argument(unsigned index, int32& value)
79 string attr_name = register_attribute_names[index];
80 assert (attr_name != "");
82 string attr_value = cpu->attribute_value (attr_name);
85 cerr << "Could not read attribute " << attr_name
86 << " for ABI argument #" << index << endl;
90 host_int_4 value_number;
91 parse_attribute(attr_value, value_number);
97 mips32_idt::set_int_result(int32 value)
100 string attr_name = register_attribute_names[-1];
101 assert (attr_name != "");
103 host_int_4 value_number = value;
104 string attr_value = make_attribute(value_number);
106 cpu->set_attribute_value (attr_name, attr_value);
107 return true; // XXX: check?
111 mips32_idt::set_error_result(int32 target_errno)
114 string attr_name = register_attribute_names[-2];
115 assert (attr_name != "");
117 host_int_4 value_number = target_errno;
118 string attr_value = make_attribute(value_number);
120 cpu->set_attribute_value (attr_name, attr_value);
121 return true; // XXX: safe to assume success?
125 mips32_idt::syscall_trap_p()
127 host_int_4 trap_type = trap_type_ipin.sense ();
128 host_int_4 trap_code = trap_code_pin.sense ();
130 // MIPS system calls work by branching to specific entry points in the
131 // ROM monitor. What we do is fill the ROM with `syscall' insns which we
133 if ((trap_type == sidutil::cpu_trap_syscall)
134 && (trap_code >= SYSCALL_MIN)
135 && (trap_code < (SYSCALL_MIN + SYSCALL_MAX)))
138 // _exit however uses the `break' insn. Lovely.
139 if (trap_type == sidutil::cpu_trap_breakpoint
140 && trap_code == BREAK_EXIT)
147 mips32_idt::syscall_trap()
151 // Turn a break exit into a syscall exit.
152 if (trap_type_ipin.sense() == sidutil::cpu_trap_breakpoint
153 && trap_code_pin.sense() == BREAK_EXIT)
154 syscall = SYSCALL_EXIT;
156 syscall = trap_code_pin.sense() - SYSCALL_MIN;
160 cerr << "MIPS/idt call number " << syscall << endl;
168 get_int_argument(1, value);
170 cerr << "*** exit(" << value << ")" << endl;
173 process_signal_pin.drive((value << 8) | newlib::sigNone);
175 process_signal_pin.drive(newlib::sigAbrt);
179 case SYSCALL_GET_MEM_INFO:
182 get_int_argument(1, bufptr);
185 string mem_size_attr = "size";
186 string attr_value = this->ram->attribute_value (mem_size_attr);
187 if (attr_value == "")
189 cerr << "Could not read ram size attribute." << endl;
192 parse_attribute(attr_value, mem_size);
193 set_word(bufptr, mem_size);
194 // instruction cache size
195 set_word(bufptr + 4, 0);
197 set_word(bufptr + 8, 0);
208 get_int_argument(1, fd);
209 get_int_argument(2, address);
210 get_int_argument(3, length);
214 if (! this->write (fd, address, length, len_written, errcode))
216 set_error_result(host_to_target_errno(errcode));
220 set_int_result(len_written);
227 cerr << "Unimplemented syscall " << syscall << endl;
230 set_error_result(newlib::eNoSys);
234 // Convert host errno value to target.
237 mips32_idt::host_to_target_errno (int host_errno)
239 return newlib::host_to_target_errno (host_errno);