-
Notifications
You must be signed in to change notification settings - Fork 2.3k
igs/pgm.cpp: one new set and another promoted to working #14981
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Osso13
wants to merge
3
commits into
mamedev:master
Choose a base branch
from
Osso13:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+838
−16
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,261 @@ | ||
| // license:BSD-3-Clause | ||
| // copyright-holders:eziochiu | ||
| // LPC2132 Vectored Interrupt Controller (VIC) | ||
| // For ARM7TDMI core interrupt controller | ||
|
|
||
| #include "emu.h" | ||
| #include "lpc2132_vic.h" | ||
|
|
||
| #define LOG_IRQ (1U << 1) | ||
| #define LOG_REG (1U << 2) | ||
|
|
||
| #define VERBOSE (0) | ||
| #include "logmacro.h" | ||
|
|
||
| DEFINE_DEVICE_TYPE(LPC2132_VIC, lpc2132_vic_device, "lpc2132_vic", "NXP LPC2132 VIC") | ||
|
|
||
| lpc2132_vic_device::lpc2132_vic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) | ||
| : device_t(mconfig, LPC2132_VIC, tag, owner, clock) | ||
| , m_irq_out(*this) | ||
| , m_fiq_out(*this) | ||
| , m_def_vect_addr_cb(*this) | ||
| { | ||
| } | ||
|
|
||
| void lpc2132_vic_device::regs_map(address_map &map) | ||
| { | ||
| map(0x000, 0x003).r(FUNC(lpc2132_vic_device::irq_status_r)); // VICIRQStatus | ||
| map(0x004, 0x007).r(FUNC(lpc2132_vic_device::fiq_status_r)); // VICFIQStatus | ||
| map(0x008, 0x00b).r(FUNC(lpc2132_vic_device::raw_intr_r)); // VICRawIntr | ||
| map(0x00c, 0x00f).rw(FUNC(lpc2132_vic_device::int_select_r), FUNC(lpc2132_vic_device::int_select_w)); // VICIntSelect | ||
| map(0x010, 0x013).rw(FUNC(lpc2132_vic_device::int_enable_r), FUNC(lpc2132_vic_device::int_enable_w)); // VICIntEnable | ||
| map(0x014, 0x017).w(FUNC(lpc2132_vic_device::int_en_clear_w)); // VICIntEnClear | ||
| map(0x018, 0x01b).rw(FUNC(lpc2132_vic_device::soft_int_r), FUNC(lpc2132_vic_device::soft_int_w)); // VICSoftInt | ||
| map(0x01c, 0x01f).w(FUNC(lpc2132_vic_device::soft_int_clear_w)); // VICSoftIntClear | ||
| map(0x020, 0x023).rw(FUNC(lpc2132_vic_device::protection_r), FUNC(lpc2132_vic_device::protection_w)); // VICProtection | ||
| map(0x030, 0x033).rw(FUNC(lpc2132_vic_device::vect_addr_r), FUNC(lpc2132_vic_device::vect_addr_w)); // VICVectAddr | ||
| map(0x034, 0x037).rw(FUNC(lpc2132_vic_device::def_vect_addr_r), FUNC(lpc2132_vic_device::def_vect_addr_w)); // VICDefVectAddr | ||
| map(0x100, 0x13f).rw(FUNC(lpc2132_vic_device::vect_addr_slot_r), FUNC(lpc2132_vic_device::vect_addr_slot_w)); // VICVectAddr0-15 | ||
| map(0x200, 0x23f).rw(FUNC(lpc2132_vic_device::vect_cntl_r), FUNC(lpc2132_vic_device::vect_cntl_w)); // VICVectCntl0-15 | ||
| } | ||
|
|
||
| void lpc2132_vic_device::device_start() | ||
| { | ||
| save_item(NAME(m_vic_irq_status)); | ||
| save_item(NAME(m_vic_fiq_status)); | ||
| save_item(NAME(m_vic_raw_intr)); | ||
| save_item(NAME(m_vic_int_select)); | ||
| save_item(NAME(m_vic_int_enable)); | ||
| save_item(NAME(m_vic_soft_int)); | ||
| save_item(NAME(m_vic_protection)); | ||
| save_item(NAME(m_vic_vect_addr)); | ||
| save_item(NAME(m_vic_vect_cntl)); | ||
| save_item(NAME(m_vic_vect_addr_cur)); | ||
| save_item(NAME(m_vic_def_vect_addr)); | ||
| } | ||
|
|
||
| void lpc2132_vic_device::device_reset() | ||
| { | ||
| m_vic_irq_status = 0; | ||
| m_vic_fiq_status = 0; | ||
| m_vic_raw_intr = 0; | ||
| m_vic_int_select = 0; | ||
| m_vic_int_enable = 0; | ||
| m_vic_soft_int = 0; | ||
| m_vic_protection = 0; | ||
| m_vic_vect_addr_cur = 0; | ||
| m_vic_def_vect_addr = 0; | ||
|
|
||
| for (auto &elem : m_vic_vect_addr) { elem = 0; } | ||
| for (auto &elem : m_vic_vect_cntl) { elem = 0; } | ||
|
|
||
| LOGMASKED(LOG_IRQ, "LPC2132 VIC: Reset complete\n"); | ||
| } | ||
|
|
||
| void lpc2132_vic_device::update_interrupt_lines() | ||
| { | ||
| // Calculate IRQ pending: enabled interrupts & raw interrupts & not FIQ selected | ||
| uint32_t irq_pending = m_vic_int_enable & m_vic_raw_intr & ~m_vic_int_select; | ||
|
|
||
| // Calculate FIQ pending: enabled interrupts & raw interrupts & FIQ selected | ||
| uint32_t fiq_pending = m_vic_int_enable & m_vic_raw_intr & m_vic_int_select; | ||
|
|
||
| m_vic_irq_status = irq_pending; | ||
|
|
||
| m_vic_fiq_status = fiq_pending; | ||
|
|
||
| // Output IRQ status | ||
| m_irq_out(irq_pending ? ASSERT_LINE : CLEAR_LINE); | ||
|
|
||
| // Output FIQ status | ||
| m_fiq_out(fiq_pending ? ASSERT_LINE : CLEAR_LINE); | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::read_vector_address() | ||
| { | ||
| uint32_t irq_pending = m_vic_int_enable & m_vic_raw_intr & ~m_vic_int_select; | ||
|
|
||
| if (irq_pending == 0) | ||
| { | ||
| m_vic_vect_addr_cur = m_vic_def_vect_addr; | ||
| return m_vic_vect_addr_cur; | ||
| } | ||
|
|
||
| // Iterate through 16 vector slots to find matching interrupt | ||
| for (int i = 0; i < 16; i++) | ||
| { | ||
| if (m_vic_vect_cntl[i] & 0x20) // Check enable bit | ||
| { | ||
| uint32_t irq_source = m_vic_vect_cntl[i] & 0x1f; | ||
|
|
||
| if (irq_pending & (1 << irq_source)) | ||
| { | ||
| m_vic_vect_addr_cur = m_vic_vect_addr[i]; | ||
| return m_vic_vect_addr_cur; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // No matching vectored interrupt, return default address | ||
| m_vic_vect_addr_cur = m_vic_def_vect_addr; | ||
| return m_vic_vect_addr_cur; | ||
| } | ||
|
|
||
| void lpc2132_vic_device::set_irq(int line, int state) | ||
| { | ||
| if (line < 0 || line >= 32) | ||
| return; | ||
|
|
||
| if (state == ASSERT_LINE) | ||
| m_vic_raw_intr |= (1 << line); | ||
| else | ||
| m_vic_raw_intr &= ~(1 << line); | ||
|
|
||
| update_interrupt_lines(); | ||
| } | ||
|
|
||
| // Register read functions | ||
| uint32_t lpc2132_vic_device::irq_status_r() | ||
| { | ||
| return m_vic_irq_status; | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::fiq_status_r() | ||
| { | ||
| return m_vic_fiq_status; | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::raw_intr_r() | ||
| { | ||
| return m_vic_raw_intr; | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::int_select_r() | ||
| { | ||
| return m_vic_int_select; | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::int_enable_r() | ||
| { | ||
| return m_vic_int_enable; | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::soft_int_r() | ||
| { | ||
| return m_vic_soft_int; | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::protection_r() | ||
| { | ||
| return m_vic_protection; | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::vect_addr_r() | ||
| { | ||
| if (!machine().side_effects_disabled()) | ||
| return read_vector_address(); | ||
|
|
||
| // when side effects are disabled (e.g. debugger), return current address without updating state | ||
| return m_vic_vect_addr_cur; | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::def_vect_addr_r() | ||
| { | ||
| return m_vic_def_vect_addr; | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::vect_addr_slot_r(offs_t offset) | ||
| { | ||
| return m_vic_vect_addr[offset]; | ||
| } | ||
|
|
||
| uint32_t lpc2132_vic_device::vect_cntl_r(offs_t offset) | ||
| { | ||
| return m_vic_vect_cntl[offset]; | ||
| } | ||
|
|
||
| // Register write functions | ||
| void lpc2132_vic_device::int_select_w(offs_t offset, uint32_t data, uint32_t mem_mask) | ||
| { | ||
| COMBINE_DATA(&m_vic_int_select); | ||
| update_interrupt_lines(); | ||
| } | ||
|
|
||
| void lpc2132_vic_device::int_enable_w(offs_t offset, uint32_t data, uint32_t mem_mask) | ||
| { | ||
| m_vic_int_enable |= (data & mem_mask); | ||
| update_interrupt_lines(); | ||
| } | ||
|
|
||
| void lpc2132_vic_device::int_en_clear_w(offs_t offset, uint32_t data, uint32_t mem_mask) | ||
| { | ||
| m_vic_int_enable &= ~(data & mem_mask); | ||
| update_interrupt_lines(); | ||
| } | ||
|
|
||
| void lpc2132_vic_device::soft_int_w(offs_t offset, uint32_t data, uint32_t mem_mask) | ||
| { | ||
| m_vic_soft_int |= (data & mem_mask); | ||
| m_vic_raw_intr |= m_vic_soft_int; | ||
| update_interrupt_lines(); | ||
| } | ||
|
|
||
| void lpc2132_vic_device::soft_int_clear_w(offs_t offset, uint32_t data, uint32_t mem_mask) | ||
| { | ||
| m_vic_soft_int &= ~(data & mem_mask); | ||
| m_vic_raw_intr &= ~(data & mem_mask); | ||
| update_interrupt_lines(); | ||
| } | ||
|
|
||
| void lpc2132_vic_device::protection_w(offs_t offset, uint32_t data, uint32_t mem_mask) | ||
| { | ||
| COMBINE_DATA(&m_vic_protection); | ||
| } | ||
|
|
||
| void lpc2132_vic_device::vect_addr_w(offs_t offset, uint32_t data, uint32_t mem_mask) | ||
| { | ||
| // Writing any value signals end of interrupt handling | ||
| // Clear the highest priority interrupt currently being processed | ||
| // We only manually clear IRQ 16 (EINT2) here as part of the handshake mechanism | ||
| if (m_vic_raw_intr & (1 << 16)) | ||
| { | ||
| m_vic_raw_intr &= ~(1 << 16); | ||
| update_interrupt_lines(); | ||
| } | ||
| } | ||
|
|
||
| void lpc2132_vic_device::def_vect_addr_w(offs_t offset, uint32_t data, uint32_t mem_mask) | ||
| { | ||
| COMBINE_DATA(&m_vic_def_vect_addr); | ||
| m_def_vect_addr_cb(m_vic_def_vect_addr); | ||
| } | ||
|
|
||
| void lpc2132_vic_device::vect_addr_slot_w(offs_t offset, uint32_t data, uint32_t mem_mask) | ||
| { | ||
| COMBINE_DATA(&m_vic_vect_addr[offset]); | ||
| } | ||
|
|
||
| void lpc2132_vic_device::vect_cntl_w(offs_t offset, uint32_t data, uint32_t mem_mask) | ||
| { | ||
| COMBINE_DATA(&m_vic_vect_cntl[offset]); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| // license:BSD-3-Clause | ||
| // copyright-holders:eziochiu | ||
|
|
||
| #ifndef MAME_MACHINE_LPC2132_VIC_H | ||
| #define MAME_MACHINE_LPC2132_VIC_H | ||
|
|
||
| #pragma once | ||
|
|
||
| DECLARE_DEVICE_TYPE(LPC2132_VIC, lpc2132_vic_device) | ||
|
|
||
| class lpc2132_vic_device : public device_t | ||
| { | ||
| public: | ||
| // construction/destruction | ||
| lpc2132_vic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); | ||
|
|
||
| // IRQ output callback | ||
| auto irq_callback() { return m_irq_out.bind(); } | ||
|
|
||
| // FIQ output callback | ||
| auto fiq_callback() { return m_fiq_out.bind(); } | ||
|
|
||
| // VICDefVectAddr write callback (for handshake detection) | ||
| auto def_vect_addr_callback() { return m_def_vect_addr_cb.bind(); } | ||
|
|
||
| // register address map | ||
| void regs_map(address_map &map) ATTR_COLD; | ||
|
|
||
| // external interrupt trigger interface | ||
| void set_irq(int line, int state); | ||
|
|
||
| // template method for interrupt line write | ||
| template<unsigned IRQ> | ||
| void irq_w(int state) { set_irq(IRQ, state); } | ||
|
|
||
| protected: | ||
| virtual void device_start() override ATTR_COLD; | ||
| virtual void device_reset() override ATTR_COLD; | ||
|
|
||
| private: | ||
| // status registers | ||
| uint32_t m_vic_irq_status; // VICIRQStatus - IRQ status | ||
| uint32_t m_vic_fiq_status; // VICFIQStatus - FIQ status | ||
| uint32_t m_vic_raw_intr; // VICRawIntr - raw interrupt status | ||
| uint32_t m_vic_int_select; // VICIntSelect - interrupt select (IRQ/FIQ) | ||
| uint32_t m_vic_int_enable; // VICIntEnable - interrupt enable | ||
| uint32_t m_vic_soft_int; // VICSoftInt - software interrupt | ||
| uint32_t m_vic_protection; // VICProtection - protection mode | ||
|
|
||
| // vector interrupt registers | ||
| uint32_t m_vic_vect_addr[16]; // VICVectAddr0-15 - vector addresses | ||
| uint32_t m_vic_vect_cntl[16]; // VICVectCntl0-15 - vector control | ||
|
|
||
| uint32_t m_vic_vect_addr_cur; // VICVectAddr - current vector address | ||
| uint32_t m_vic_def_vect_addr; // VICDefVectAddr - default vector address | ||
|
|
||
| // IRQ output | ||
| devcb_write_line m_irq_out; | ||
|
|
||
| // FIQ output | ||
| devcb_write_line m_fiq_out; | ||
|
|
||
| // VICDefVectAddr write callback | ||
| devcb_write32 m_def_vect_addr_cb; | ||
|
|
||
| // internal functions | ||
| void update_interrupt_lines(); | ||
| uint32_t read_vector_address(); | ||
|
|
||
| // register read functions | ||
| uint32_t irq_status_r(); | ||
| uint32_t fiq_status_r(); | ||
| uint32_t raw_intr_r(); | ||
| uint32_t int_select_r(); | ||
| uint32_t int_enable_r(); | ||
| uint32_t soft_int_r(); | ||
| uint32_t protection_r(); | ||
| uint32_t vect_addr_r(); | ||
| uint32_t def_vect_addr_r(); | ||
| uint32_t vect_addr_slot_r(offs_t offset); | ||
| uint32_t vect_cntl_r(offs_t offset); | ||
|
|
||
| // register write functions | ||
| void int_select_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); | ||
| void int_enable_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); | ||
| void int_en_clear_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); | ||
| void soft_int_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); | ||
| void soft_int_clear_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); | ||
| void protection_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); | ||
| void vect_addr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); | ||
| void def_vect_addr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); | ||
| void vect_addr_slot_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); | ||
| void vect_cntl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); | ||
| }; | ||
|
|
||
| #endif // MAME_MACHINE_LPC2132_VIC_H |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this have side effect checks?