summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mcs40
Commit message (Collapse)AuthorAgeFilesLines
* misc cpu: no need to check debug enabled flag manually hap2025-04-111-1/+1
|
* -machine/spi_sdcard.cpp: Generate appropriate CSD for mounted image. Vas Crabb2024-10-012-10/+22
| | | | | | | | | | | | * The Linux/4004 firmware gets very upset if the CSD looks like an SDHC Card but the card acts like an SD Card or vice versa. -machine/spi_psram.cpp: Added SPI ram device compatible with SPI SRAM and Pseudo-SRAM chips for small transfers. Additional functionality will be added as use cases arise. -cpu/mcs40: Don't log messages about NOP aliases for the 4004 (the Linux/4004 firmware uses these for instrumentation points).
* Added ATTR_COLD to common lifecycle methods for many files in src/devices. ↵ holub2024-09-271-2/+2
| | | | (#12822)
* diexec: remove vestigal execute_input_lines() hap2024-09-182-12/+0
|
* emu/devcb.h: Eliminated the need to call resolve() on callbacks. (#11333) Vas Crabb2023-06-171-7/+0
| | | | | | | | | | | | Read callbacks now need a default return value supplied at construction. Replaced isnull() with isunset() which tells you if the callback wasn't configured rather than whether it isn't safe to call. Enabled validation of device callbacks (it seems it was disabled at some point, probably accidentally). Device callbacks and object finders now implement the same interface for resolution.
* emu/devdelegate.h: Added resolve_safe and resolve_all_safe helpers. Vas Crabb2023-06-131-17/+9
| | | | | | | | | Uses decay rules, so if a delegate returns a reference and you want to supply a referene to an object you don't want copied as the default result, remember to use std::ref. Updated a few devices to use resolve_safe on device delegates to streamline code.
* emu/device.h: Removed device (READ|WRITE)_LINE_MEMBER in favor of explicit ↵ MooglyGuy2023-06-011-2/+2
| | | | function signatures. (#11283) [Ryan Holtz]
* src/devices/cpu: Remove #include "debugger.h" where no longer necessary AJR2022-04-061-1/+0
|
* Debugger feature improvements AJR2022-03-271-1/+3
| | | | | | | | - Add 'gbt' and 'gbf' debugger commands to step until a true or false conditional branch has been detected. - Update over 100 of the disassemblers in MAME to output a new STEP_COND flag for all conditional branches. Besides being used for execution of the new 'gbt' and 'gbf' commands, this flag also now helps the debugger 'out' command to properly handle conditional return instructions. - Remove STEP_OVER from many instructions that aren't actually subroutine calls (e.g. DJNZ on Z80). A 'gni' debugger command (go next instruction) has been added to accommodate some of the misuse. - Add instruction flag support to several more disassemblers that lacked them entirely (e.g. st62xx) - Don't pass over delay slots for debugging in ASAP core
* emumem: A little more speedup. cache and specific change syntax, and are ↵ Olivier Galibert2020-05-252-5/+4
| | | | | | | | | | | | | | | | not pointers anymore [O. Galibert] The last(?) two changes are: - Add a template parameter to everything (theoretically the address space width, in practice a level derived from it to keep as much compatibility between widths as possible) so that the shift size becomes a constant. - Change the syntax of declaring and initializing the caches and specifics so that they're embedded in the owner device. Solves lifetime issues and also removes one indirection (looking up the base dispatch pointer through the cache/specific pointer).
* sweeten most of the remaining arrays of delegates (nw) Vas Crabb2020-02-072-13/+10
|
* Make many device_execute_interface functions noexcept, including the ↵ AJR2019-11-092-4/+4
| | | | | | | | "information" overrides. This also covers several time-related functions in attotime, running_machine and emu_timer. (nw) m6805: Calculate min_cycles and max_cycles once at device_start time (Nw) attotime: Add as_khz and as_mhz (nw)
* Make devdelegate more like devcb for configuration. This is a Vas Crabb2019-10-262-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | fundamental change to show device delegates are configured. Device delegates are now aware of the current device during configuration and will resolve string tags relative to it. This means that device delegates need a device to be supplied on construction so they can find the machine configuration object. There's a one-dimensional array helper to make it easier to construct arrays of device delegates with the same owner. (I didn't make an n-dimensional one because I didn't hit a use case, but it would be a simple addition.) There's no more bind_relative_to member - just call resolve() like you would for a devcb. There's also no need to cast nullptr when creating a late bind device delegate. The flip side is that for an overloaded or non-capturing lambda you'll need to cast to the desired type. There is one less conditional branch in the hot path for calls for delegates bound to a function pointer of member function pointer. This comes at the cost of one additional unconditional branch in the hot path for calls to delegates bound to functoids (lambdas, functions that don't take an object reference, other callable objects). This applies to all delegates, not just device delegates. Address spaces will now print an error message if a late bind error is encountered while installing a handler. This will give the range and address range, hopefully making it easier to guess which memory map is faulty. For the simple case of allowing a device_delegate member to be configured, use a member like this: template <typename... T> void set_foo(T &&...args) { m_foo_cb.set(std::forward<T>(args)...); } For a case where different delegates need to be used depending on the function signature, see src/emu/screen.h (the screen update function setters). Device delegates now take a target specification and function pointer. The target may be: * Target omitted, implying the current device being configured. This can only be used during configuration. It will work as long as the current device is not removed/replaced. * A tag string relative to the current device being configured. This can only be used during configuration. It will not be callable until .resolve() is called. It will work as long as the current device is not removed/replaced. * A device finder (required_device/optional_device). The delegate will late bind to the current target of the device finder. It will not be callable until .resolve() is called. It will work properly if the target device is replaced, as long as the device finder's base object isn't removed/replaced. * A reference to an object. It will be callable immediately. It will work as long as the target object is not removed/replaced. The target types and restrictions are pretty similar to what you already have on object finders and devcb, so it shouldn't cause any surprises. Note that dereferencing a device finder will changes the effect. To illustrate this: ... required_device<some_device> m_dev; ... m_dev(*this, "dev") ... // will late bind to "dev" relative to *this // will work if "dev" hasn't been created yet or is replaced later // won't work if *this is removed/replaced // won't be callable until resolve() is called cb1.set(m_dev, FUNC(some_device::w)); ... // will bind to current target of m_dev // will not work if m_dev is not resolved // will not work if "dev" is replaced later // will be callable immediately cb2.set(*m_dev, FUNC(some_device::w)); ... The order of the target and name has been reversed for functoids (lambdas and other callable objects). This allows the NAME macro to be used on lambdas and functoids. For example: foo.set_something(NAME([this] (u8 data) { m_something = data; })); I realise the diagnostic messages get ugly if you use NAME on a large lambda. You can still give a literal name, you just have to place it after the lambda rather than before. This is uglier, but it's intentional. I'm trying to drive developers away from a certain style. While it's nice that you can put half the driver code in the memory map, it detracts from readability. It's hard to visualise the memory range mappings if the memory map functions are punctuated by large lambdas. There's also slightly higher overhead for calling a delegate bound to a functoid. If the code is prettier for trivial lambdas but uglier for non-trivial lambdas in address maps, it will hopefully steer people away from putting non-trivial lambdas in memory maps. There were some devices that were converted from using plain delegates without adding bind_relative_to calls. I fixed some of them (e.g. LaserDisc) but I probably missed some. These will likely crash on unresolved delegate calls. There are some devices that reset delegates at configuration complete or start time, preventing them from being set up during configuration (e.g. src/devices/video/ppu2c0x.cpp and src/devices/machine/68307.cpp). This goes against the design principles of how device delegates should be used, but I didn't change them because I don't trust myself to find all the places they're used. I've definitely broken some stuff with this (I know about asterix), so report issues and bear with me until I get it all fixed.
* cherry-pick fixes from mainline and clean up some stuff (nw) Vas Crabb2018-07-231-15/+2
|
* appease msvc (nw) smf-2018-07-211-4/+4
|
* Allow per-device internal layouts and remove some more MCFG_ macros. Vas Crabb2018-07-161-98/+24
| | | | | | | | | | | Input and screen tags are now resolved relative to a layout's owner device. Easy way to demonstrate is with: mame64 intlc440 -tty ie15 Previously you'd only get the IE15 terminal's layout and you'd be unable to use the INTELLEC 4/40 front panel. Now you'll get the choice of layouts from both the system and the terminal device in video options.
* devcb3 Vas Crabb2018-07-071-19/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | There are multiple issues with the current device callbacks: * They always dispatch through a pointer-to-member * Chained callbacks are a linked list so the branch unit can't predict the early * There's a runtime decision made on the left/right shift direction * There are runtime NULL checks on various objects * Binding a lambda isn't practical * Arbitrary transformations are not supported * When chaining callbacks it isn't clear what the MCFG_DEVCB_ modifiers apply to * It isn't possible to just append to a callback in derived configuration * The macros need a magic, hidden local called devcb * Moving code that uses the magic locals around is error-prone * Writing the MCFG_ macros to make a device usable is a pain * You can't discover applicable MCFG_ macros with intellisense * Macros are not scoped * Using an inappropriate macro isn't detected at compile time * Lots of other things This changeset overcomes the biggest obstacle to remving MCFG_ macros altogether. Essentially, to allow a devcb to be configured, call .bind() and expose the result (a bind target for the callback). Bind target methods starting with "set" repace the current callbacks; methods starting with "append" append to them. You can't reconfigure a callback after resolving it. There's no need to use a macro matching the handler signatures - use FUNC for everything. Current device is implied if no tag/finder is supplied (no need for explicit this). Lambdas are supported, and the memory space and offset are optional. These kinds of things work: * .read_cb().set([this] () { return something; }); * .read_cb().set([this] (offs_t offset) { return ~offset; }); * .write_cb().set([this] (offs_t offset, u8 data) { m_array[offset] = data; }); * .write_cb().set([this] (int state) { some_var = state; }); Arbitrary transforms are allowed, and they can modify offset/mask for example: * .read_cb().set(FUNC(my_state::handler)).transform([] (u8 data) { return bitswap<4>(data, 1, 3, 0, 2); }); * .read_cb().set(m_dev, FUNC(some_device::member)).transform([] (offs_t &offset, u8 data) { offset ^= 3; return data; }); It's possible to stack arbitrary transforms, at the cost of compile time (the whole transform stack gets inlined at compile time). Shifts count as an arbitrary transform, but mask/exor does not. Order of mask/shift/exor now matters. Modifications are applied in the specified order. These are NOT EQUIVALENT: * .read_cb().set(FUNC(my_state::handler)).mask(0x06).lshift(2); * .read_cb().set(FUNC(my_state::handler)).lshift(2).mask(0x06); The bit helper no longer reverses its behaviour for read callbacks, and I/O ports are no longer aware of the field mask. Binding a read callback to no-op is not supported - specify a constant. The GND and VCC aliases have been removed intentionally - they're TTL-centric, and were already being abused. Other quirks have been preserved, including write logger only logging when the data is non-zero (quite unhelpful in many of the cases where it's used). Legacy syntax is still supported for simple cases, but will be phased out. New devices should not have MCFG_ macros. I don't think I've missed any fundamental issues, but if I've broken something, let me know.
* Allow passing std::unique_ptr<TYPE> directly to save_pointer and remove ↵ AJR2018-06-241-2/+2
| | | | now-superfluous .get() in many drivers/devices (nw)
* mcs40: cleaner boilerplate (nw) Vas Crabb2018-06-071-36/+9
|
* emumem: Rename direct_read_handler to memory_access_cache. Parametrize the ↵ Olivier Galibert2018-05-112-5/+5
| | | | template on more information (data width, endianness) to make it possible to turn it into an handler cache eventually, and not just a memory block cache. Make it capable of large and unaligned accesses. [O. Galibert]
* Reshuffle some stuff: Vas Crabb2018-03-281-2/+2
| | | | | | * Move around the debugger hooks to get a small but measurable performance increase * Remove emucore from external tools * Improve performance of DSP16 interpreter a little by generating six variants of execution loop
* don't pass so many naked pointers around (nw) Vas Crabb2018-03-252-6/+6
|
* destaticify initializations (nw) (#3289) wilbertpol2018-03-041-53/+37
| | | | | | * destaticify initializations (nw) * fix this->set_screen (nw)
* New machines marked NOT_WORKING Vas Crabb2018-01-141-1/+1
| | | | | ------------------------------- Sartorius-Werke GmbH 3733 [Mike McBike, rfka01, Vas Crabb]
* MCS-40 is paged (nw) Vas Crabb2017-12-013-7/+10
|
* emumem: API change [O. Galibert] Olivier Galibert2017-11-292-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * direct_read_data is now a template which takes the address bus shift as a parameter. * address_space::direct<shift>() is now a template method that takes the shift as a parameter and returns a pointer instead of a reference * the address to give to {read|write}_* on address_space or direct_read_data is now the address one wants to access Longer explanation: Up until now, the {read|write}_* methods required the caller to give the byte offset instead of the actual address. That's the same on byte-addressing CPUs, e.g. the ones everyone knows, but it's different on the word/long/quad addressing ones (tms, sharc, etc...) or the bit-addressing one (tms340x0). Changing that required templatizing the direct access interface on the bus addressing granularity, historically called address bus shift. Also, since everybody was taking the address of the reference returned by direct(), and structurally didn't have much choice in the matter, it got changed to return a pointer directly. Longest historical explanation: In a cpu core, the hottest memory access, by far, is the opcode fetching. It's also an access with very good locality (doesn't move much, tends to stay in the same rom/ram zone even when jumping around, tends not to hit handlers), which makes efficient caching worthwhile (as in, 30-50% faster core iirc on something like the 6502, but that was 20 years ago and a number of things changed since then). In fact, opcode fetching was, in the distant past, just an array lookup indexed by pc on an offset pointer, which was updated on branches. It didn't stay that way because more elaborate access is often needed (handlers, banking with instructions crossing a bank...) but it still ends up with a frontend of "if the address is still in the current range read from pointer+address otherwise do the slowpath", e.g. two usually correctly predicted branches plus the read most of the time. Then the >8 bits cpus arrived. That was ok, it just required to do the add to a u8 *, then convert to a u16/u32 * and do the read. At the asm level, it was all identical except for the final read, and read_byte/word/long being separate there was no test (and associated overhead) added in the path. Then the word-addressing CPUs arrived with, iirc, the tms cpus used in atari games. They require, to read from the pointer, to shift the address, either explicitely, or implicitely through indexing a u16 *. There were three possibilities: 1- create a new read_* method for each size and granularity. That amounts to a lot of copy/paste in the end, and functions with identical prototypes so the compiler can't detect you're using the wrong one. 2- put a variable shift in the read path. That was too expensive especially since the most critical cpus are byte-addressing (68000 at the time was the key). Having bit-adressing cpus which means the shift can either be right or left depending on the variable makes things even worse. 3- require the caller to do the shift himself when needed. The last solution was chosen, and starting that day the address was a byte offset and not the real address. Which is, actually, quite surprising when writing a new cpu core or, worse, when using the read/write methods from the driver code. But since then, C++ happened. And, in particular, templates with non-type parameters. Suddendly, solution 1 can be done without the copy/paste and with different types allowing to detect (at runtime, but systematically and at startup) if you got it wrong, while still generating optimal code. So it was time to switch to that solution and makes the address parameter sane again. Especially since it makes mucking in the rest of the memory subsystem code a lot more understandable.
* Build fixes (nw) AJR2017-11-261-0/+1
|
* dvdisasm: Overhaul [O. Galibert] Olivier Galibert2017-11-264-106/+122
| | | | | | | | Disassemblers are now independant classes. Not only the code is cleaner, but unidasm has access to all the cpu cores again. The interface to the disassembly method has changed from byte buffers to objects that give a result to read methods. This also adds support for lfsr and/or paged PCs.
* explicit sizes for enums used in save states - one should always do this to ↵ Vas Crabb2017-07-161-3/+3
| | | | maximise save state compatibility - also enum class (nw)
* wtf (nw) Vas Crabb2017-07-111-1/+1
|
* make device_memory_interface slightly less of a special case, use a typedef ↵ Vas Crabb2017-07-102-3/+3
| | | | to avoid nested templates everywhere (nw)
* New machines marked NOT_WORKING Vas Crabb2017-07-091-3/+3
| | | | | ------------------------------ INTELLEC 4/MOD 4
* (nw) notes, coverity complaints, INTELLEC 4/MOD 4 layout, detect duplicate ↵ Vas Crabb2017-07-091-2/+2
| | | | bounds/color in layouts
* fix for building with MSVC, it can't cope with the collision with the FUNC() ↵ smf-2017-07-081-3/+3
| | | | macro. (nw)
* intlc440: one more front panel switch (nw) Vas Crabb2017-07-071-6/+3
|
* mcs40 updates: Vas Crabb2017-07-062-100/+204
| | | | | | | | | | | | * Split ROM and RAM port address spaces * Split RAM memory and status address spaces (no more read/modify/write) * Fixed bug in FIN handling * Exposed cycle callback * Implemented most of intelc440 front panel * Added preliminary internal artwork for intlc440 * Re-implmented flicker I/O based on how hardware actually works * Corrected flicker RAM size * Hooked up flicker playfield lamp outputs - this really needs PWM
* dimemory: Lift the cap on the number of address spaces per device [O. Galibert] Olivier Galibert2017-07-032-11/+9
|
* Rename AS_DECRYPTED_OPCODES to AS_OPCODES [O. Galibert] Olivier Galibert2017-07-031-2/+2
|
* intlc440 improvements: Vas Crabb2017-07-012-5/+16
| | | | | | | | | | * Implemented front panel mode switches/LEDs and reset switch * Added skeleton bus for "universal" slots and connected control lines (nw) Default keyboard mapping is annoying because left shift, Z and X are used both for typing into the TTY and switching program bank. You're better off changing the mapping to make it less annoying or using a socket and talking to it with telnet.
* Add support for 4040 stop/ack and HLT instruction, hook up stop/single step ↵ Vas Crabb2017-06-292-126/+283
| | | | buttons in INTELLEC 4/MOD 40
* fixup (nw) Vas Crabb2017-06-293-22/+15
| | | | | | * can't use opram when program and opcodes are not related in the slightest * check for disabled side-effects! * better reflection of 4289 timings for performing program read/write
* MCS-40 and INTELLEC 4/MOD 40 updates: Vas Crabb2017-06-293-155/+255
| | | | | | | | | | | | * Make disassembler/debugger use syntax closer to what ASL accepts * Use 2D lookup to make debugger tables more compact * Allow 4-bit registers to be set independently * Save state fixes * Implement WPM/RPM instructions * Expose some signals from a 4008/4009 or 4289 * Implement RAM read/write mechanism for INTELLEC 4/MOD 40 - Can test with S and D commands in monitor * Connect INTELLEC 4/MOD 40 paper tape run output to RTS on RS232 port
* Build fixes (nw) AJR2017-06-261-1/+0
|
* Rewrote 4004 core and disassembler: Vas Crabb2017-06-273-0/+1518
* Renamed to MCS-40. * Emulated 8-clock instruction cycle, interruptible at any point. * Converted TEST input to an input line. * Added SYNC and CM output lines. * Added support for 4040 CY output, logical operations, extended registers, ROM banking and disassembly. * Made I/O space mapping more flexible to support the variety of peripherals available. * Notable missing features are 4040 interrupt and halt, and "program memory" space.