Merge branch 'master' into cpu-refactor2

This commit is contained in:
dingusdev 2024-03-25 07:45:21 -07:00 committed by GitHub
commit 3c3d0b46db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 856 additions and 274 deletions

File diff suppressed because it is too large Load Diff

View File

@ -24,12 +24,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes>
#include <string>
#include <vector>
typedef struct PPCDisasmContext {
uint32_t instr_addr;
uint32_t instr_code;
std::string instr_str;
bool simplified; /* true if we should output simplified mnemonics */
std::vector<std::string> regs_in;
std::vector<std::string> regs_out;
} PPCDisasmContext;
std::string disassemble_single(PPCDisasmContext* ctx);

View File

@ -115,7 +115,7 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) {
ppc_state.spr[SPR::SRR1] = (ppc_state.msr & 0x0000FF73) | srr1_bits;
ppc_state.msr &= 0xFFFB1041;
/* copy MSR[ILE] to MSR[LE] */
ppc_state.msr = (ppc_state.msr & 0xFFFFFFFE) | ((ppc_state.msr >> 16) & 1);
ppc_state.msr = (ppc_state.msr & ~MSR::LE) | !!(ppc_state.msr & MSR::ILE);
if (ppc_state.msr & MSR::IP) {
ppc_next_instruction_address |= 0xFFF00000;

View File

@ -94,7 +94,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
uint32_t ppc_result_b = ppc_state.gpr[reg_b];
#define ppc_store_iresult_reg(reg, ppc_result)\
ppc_state.gpr[(reg)] = ppc_result;
ppc_state.gpr[reg] = ppc_result;
#define ppc_store_sfpresult_int(reg, ppc_result64_d)\
ppc_state.fpr[(reg)].int64_r = ppc_result64_d;

View File

@ -391,7 +391,7 @@ void mmu_change_mode()
break;
case 1:
// user mode can't disable translations
LOG_F(ERROR, "instruction mmu mode 1 is invalid!");
//LOG_F(ERROR, "instruction mmu mode 1 is invalid!"); // this happens alot. Maybe it's not invalid?
mmu_mode = 3;
case 3: // user mode with instruction translation enabled
pCurITLB1 = &itlb1_mode3[0];

View File

@ -528,7 +528,7 @@ void dppc_interpreter::ppc_mulli() {
template <bool rec, bool ov>
void dppc_interpreter::ppc_divw() {
uint32_t ppc_result_d;
uint32_t ppc_result_d = 0;
ppc_grab_regsdab(ppc_cur_instruction);
if (!ppc_result_b) { /* handle the "anything / 0" case */
@ -564,7 +564,7 @@ template void dppc_interpreter::ppc_divw<RC1, OV1>();
template <bool rec, bool ov>
void dppc_interpreter::ppc_divwu() {
uint32_t ppc_result_d;
uint32_t ppc_result_d = 0;
ppc_grab_regsdab(ppc_cur_instruction);
if (!ppc_result_b) { /* division by zero */

View File

@ -96,7 +96,7 @@ uint8_t AdbBus::process_command(const uint8_t* in_data, int data_size) {
if (!this->got_answer)
return ADB_STAT_TIMEOUT;
} else {
ABORT_F("%s: unsupported ADB command 0x%X", this->name.c_str(), cmd_byte);
LOG_F(ERROR, "%s: unsupported ADB command 0x%X", this->name.c_str(), cmd_byte);
}
return ADB_STAT_OK;

View File

@ -130,7 +130,7 @@ void DMAChannel::finish_cmd() {
this->cur_cmd = cmd_desc[3] >> 4;
// all commands except STOP update cmd.xferStatus and
// perform actions under control of "i", "b" and "w" bits
// perform actions under control of "i" interrupt, "b" branch, and "w" wait bits
if (this->cur_cmd < DBDMA_Cmd::STOP) {
// react to cmd.w (wait) bits
if (cmd_desc[2] & 3) {
@ -258,7 +258,10 @@ void DMAChannel::update_irq() {
}
}
if (cond) {
this->int_ctrl->ack_dma_int(this->irq_id, 1);
if (int_ctrl)
this->int_ctrl->ack_dma_int(this->irq_id, 1);
else
LOG_F(ERROR, "%s Interrupt ignored", this->get_name().c_str());
}
}
}
@ -344,8 +347,10 @@ void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size) {
break;
case DMAReg::CH_STAT:
break; // ingore writes to ChannelStatus
case DMAReg::CMD_PTR_HI: // Mac OS X writes this optional register with zero
LOG_F(9, "CommandPtrHi set to 0x%X", value);
case DMAReg::CMD_PTR_HI:
if (value != 0) {
LOG_F(WARNING, "%s: Unsupported DMA channel register write @%02x.%c = %0*x", this->get_name().c_str(), offset, SIZE_ARG(size), size * 2, value);
}
break;
case DMAReg::CMD_PTR_LO:
if (!(this->ch_stat & CH_STAT_RUN) && !(this->ch_stat & CH_STAT_ACTIVE)) {
@ -462,11 +467,11 @@ void DMAChannel::start() {
this->queue_len = 0;
this->cmd_in_progress = false;
if (this->start_cb)
this->start_cb();
this->cmd_in_progress = false;
// some DBDMA programs contain commands that don't transfer data
// between a device and memory (LOAD_QUAD, STORE_QUAD, NOP and STOP).
// We thus interprete the DBDMA program until a data transfer between

View File

@ -40,28 +40,48 @@ class InterruptCtrl;
enum DMAReg : uint32_t {
CH_CTRL = 0,
CH_STAT = 4,
CMD_PTR_HI = 8,
CMD_PTR_HI = 8, // not implemented
CMD_PTR_LO = 12,
INT_SELECT = 16,
BRANCH_SELECT = 20,
WAIT_SELECT = 24,
// TANSFER_MODES = 28,
// DATA_2_PTR_HI = 32, // not implemented
// DATA_2_PTR_LO = 36,
// RESERVED_1 = 40,
// ADDRESS_HI = 44,
// RESERVED_2_0 = 48,
// RESERVED_2_1 = 52,
// RESERVED_2_2 = 56,
// RESERVED_2_3 = 60,
// UNIMPLEMENTED = 64,
// UNDEFINED = 128,
};
/** Channel Status bits (DBDMA spec, 5.5.3) */
enum : uint16_t {
CH_STAT_ACTIVE = 0x400,
CH_STAT_DEAD = 0x800,
CH_STAT_WAKE = 0x1000,
CH_STAT_FLUSH = 0x2000,
CH_STAT_PAUSE = 0x4000,
CH_STAT_RUN = 0x8000
CH_STAT_S0 = 0x0001, // general purpose status and control
CH_STAT_S1 = 0x0002, // general purpose status and control
CH_STAT_S2 = 0x0004, // general purpose status and control
CH_STAT_S3 = 0x0008, // general purpose status and control
CH_STAT_S4 = 0x0010, // general purpose status and control
CH_STAT_S5 = 0x0020, // general purpose status and control
CH_STAT_S6 = 0x0040, // general purpose status and control
CH_STAT_S7 = 0x0080, // general purpose status and control
CH_STAT_BT = 0x0100, // hardware status bit
CH_STAT_ACTIVE = 0x0400, // hardware status bit
CH_STAT_DEAD = 0x0800, // hardware status bit
CH_STAT_WAKE = 0x1000, // command bit set by software and cleared by hardware once the action has been performed
CH_STAT_FLUSH = 0x2000, // command bit set by software and cleared by hardware once the action has been performed
CH_STAT_PAUSE = 0x4000, // control bit set and cleared by software
CH_STAT_RUN = 0x8000 // control bit set and cleared by software
};
/** DBDMA command (DBDMA spec, 5.6.1) - all fields are little-endian! */
typedef struct DMACmd {
uint16_t req_count;
uint8_t cmd_bits;
uint8_t cmd_key;
uint8_t cmd_bits; // wait: & 3, branch: & 0xC, interrupt: & 0x30, reserved: & 0xc0
uint8_t cmd_key; // key: & 7, reserved: & 8, cmd: >> 4
uint32_t address;
uint32_t cmd_arg;
uint16_t res_count;

View File

@ -36,4 +36,7 @@ public:
virtual ~MMIODevice() = default;
};
#define SIZE_ARG(size) (size == 4 ? 'l' : size == 2 ? 'w' : \
size == 1 ? 'b' : '0' + size)
#endif /* MMIO_DEVICE_H */

View File

@ -197,9 +197,6 @@ inline uint32_t pci_cfg_log(uint32_t value, AccessDetails &details) {
}
}
#define SIZE_ARG(size) (size == 4 ? 'l' : size == 2 ? 'w' : \
size == 1 ? 'b' : '0' + size)
#define LOG_READ_UNIMPLEMENTED_CONFIG_REGISTER() \
do { if ((details.flags & PCI_CONFIG_DIRECTION) == PCI_CONFIG_READ) { \
VLOG_F( \

View File

@ -185,6 +185,10 @@ uint16_t Sc53C94::pseudo_dma_read()
}
}
}
else {
LOG_F(ERROR, "SC53C94: FIFO underrun %d", data_fifo_pos);
data_word = 0;
}
// see if we need to refill FIFO
if (!this->data_fifo_pos && !is_done) {

View File

@ -28,7 +28,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <machines/machineproperties.h>
#include <memaccess.h>
#include <cinttypes>
#include <cstring>
using namespace std;
@ -239,7 +238,7 @@ static char Apple_Copyright_Page_Data[] = "APPLE COMPUTER, INC ";
void ScsiCdrom::mode_sense()
{
uint8_t page_code = this->cmd_buf[2] & 0x3F;
uint8_t alloc_len = this->cmd_buf[4];
//uint8_t alloc_len = this->cmd_buf[4];
int num_blocks = this->size_blocks;

View File

@ -82,7 +82,8 @@ void AwacsBase::dma_out_start() {
if (!this->out_stream_running) {
if ((err = snd_server->start_out_stream())) {
LOG_F(ERROR, "%s: could not start sound output stream", this->name.c_str());
LOG_F(ERROR, "%s: could not start sound output stream: %d",
this->name.c_str(), err);
}
}
}

View File

@ -62,7 +62,9 @@ uint32_t BurgundyCodec::snd_ctrl_read(uint32_t offset, int size) {
}
void BurgundyCodec::snd_ctrl_write(uint32_t offset, uint32_t value, int size) {
uint8_t reg_addr, cur_byte, last_byte;
uint8_t reg_addr;
uint8_t cur_byte;
//uint8_t last_byte;
value = BYTESWAP_32(value);
@ -71,7 +73,7 @@ void BurgundyCodec::snd_ctrl_write(uint32_t offset, uint32_t value, int size) {
this->last_ctrl_data = value;
reg_addr = (value >> 12) & 0xFF;
cur_byte = (value >> 8) & 3;
last_byte = (value >> 10) & 3;
//last_byte = (value >> 10) & 3;
if (value & BURGUNDY_REG_WR) {
uint32_t mask = 0xFFU << (cur_byte * 8);
this->reg_array[reg_addr] = (this->reg_array[reg_addr] & ~mask) |

View File

@ -686,28 +686,21 @@ void AtiMach64Gx::crtc_update()
this->crtc_on = true;
}
void AtiMach64Gx::draw_hw_cursor(uint8_t *dst_buf, int dst_pitch) {
uint8_t *src_buf, *src_row, *dst_row, px4;
void AtiMach64Gx::draw_hw_cursor(uint8_t *dst_row, int dst_pitch) {
int vert_offset = extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_OFF], ATI_CUR_VERT_OFF, ATI_CUR_VERT_OFF_size);
//int horz_offset = extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_OFF], ATI_CUR_HORZ_OFF, ATI_CUR_HORZ_OFF_size);
src_buf = &this->vram_ptr[this->regs[ATI_CUR_OFFSET] * 8];
int cur_height = 64 - vert_offset;
uint32_t color0 = this->regs[ATI_CUR_CLR0] | 0x000000FFUL;
uint32_t color1 = this->regs[ATI_CUR_CLR1] | 0x000000FFUL;
for (int h = 0; h < cur_height; h++) {
dst_row = &dst_buf[h * dst_pitch];
src_row = &src_buf[h * 16];
uint64_t *src_row = (uint64_t *)&this->vram_ptr[this->regs[ATI_CUR_OFFSET] * 8];
dst_pitch -= 64 * 4;
for (int x = 0; x < 16; x++) {
px4 = src_row[x];
for (int p = 0; p < 4; p++, px4 >>= 2, dst_row += 4) {
switch(px4 & 3) {
for (int h = cur_height; h > 0; h--) {
for (int x = 2; x > 0; x--) {
uint64_t px = *src_row++;
for (int p = 32; p > 0; p--, px >>= 2, dst_row += 4) {
switch(px & 3) {
case 0: // cursor color 0
WRITE_DWORD_BE_A(dst_row, color0);
break;
@ -718,15 +711,18 @@ void AtiMach64Gx::draw_hw_cursor(uint8_t *dst_buf, int dst_pitch) {
WRITE_DWORD_BE_A(dst_row, 0);
break;
case 3: // 1's complement of display pixel
WRITE_DWORD_BE_A(dst_row, 0x0000007F);
break;
}
}
}
dst_row += dst_pitch;
}
}
void AtiMach64Gx::get_cursor_position(int& x, int& y) {
x = extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_POSN], ATI_CUR_HORZ_POSN, ATI_CUR_HORZ_POSN_size);
x = extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_POSN], ATI_CUR_HORZ_POSN, ATI_CUR_HORZ_POSN_size) -
extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_OFF ], ATI_CUR_HORZ_OFF , ATI_CUR_HORZ_OFF_size );
y = extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_POSN], ATI_CUR_VERT_POSN, ATI_CUR_VERT_POSN_size);
}

View File

@ -385,6 +385,16 @@ void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) {
}
}
break;
case ATI_CUR_CLR0:
case ATI_CUR_CLR1:
this->setup_hw_cursor();
// fallthrough
case ATI_CUR_OFFSET:
case ATI_CUR_HORZ_VERT_POSN:
case ATI_CUR_HORZ_VERT_OFF:
new_value = value;
draw_fb = true;
break;
case ATI_GP_IO:
new_value = value;
if (offset <= 1 && offset + size > 1) {
@ -446,6 +456,7 @@ void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) {
this->setup_hw_cursor();
else
this->cursor_on = false;
draw_fb = true;
}
if (bit_changed(old_value, new_value, ATI_GEN_GUI_RESETB)) {
if (!bit_set(new_value, ATI_GEN_GUI_RESETB))
@ -549,9 +560,11 @@ void ATIRage::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int siz
{
if (rgn_start == this->aperture_base[0] && offset < this->aperture_size[0]) {
if (offset < this->vram_size) { // little-endian VRAM region
draw_fb = true;
return write_mem(&this->vram_ptr[offset], value, size);
}
if (offset >= BE_FB_OFFSET) { // big-endian VRAM region
draw_fb = true;
return write_mem(&this->vram_ptr[offset & (BE_FB_OFFSET - 1)], value, size);
}
//if (!bit_set(this->regs[ATI_BUS_CNTL], ATI_BUS_APER_REG_DIS)) {
@ -695,38 +708,45 @@ void ATIRage::crtc_update() {
switch (this->pixel_format) {
case 1:
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_4bpp_indexed(dst_buf, dst_pitch);
};
break;
case 2:
if (bit_set(this->regs[ATI_DAC_CNTL], ATI_DAC_DIRECT)) {
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_8bpp(dst_buf, dst_pitch);
};
}
else {
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_8bpp_indexed(dst_buf, dst_pitch);
};
}
break;
case 3:
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_15bpp_BE(dst_buf, dst_pitch);
};
break;
case 4:
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_16bpp(dst_buf, dst_pitch);
};
break;
case 5:
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_24bpp(dst_buf, dst_pitch);
};
break;
case 6:
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_32bpp_BE(dst_buf, dst_pitch);
};
break;
@ -757,47 +777,44 @@ void ATIRage::crtc_update() {
this->crtc_on = true;
}
void ATIRage::draw_hw_cursor(uint8_t *dst_buf, int dst_pitch) {
uint8_t *src_buf, *src_row, *dst_row, px4;
int vert_offset = extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_OFF], ATI_CUR_VERT_OFF, ATI_CUR_VERT_OFF_size);
src_buf = &this->vram_ptr[this->regs[ATI_CUR_OFFSET] * 8];
void ATIRage::draw_hw_cursor(uint8_t* dst_row, int dst_pitch) {
int vert_offset = extract_bits<uint32_t>(
this->regs[ATI_CUR_HORZ_VERT_OFF], ATI_CUR_VERT_OFF, ATI_CUR_VERT_OFF_size);
int cur_height = 64 - vert_offset;
uint32_t color0 = this->regs[ATI_CUR_CLR0] | 0x000000FFUL;
uint32_t color1 = this->regs[ATI_CUR_CLR1] | 0x000000FFUL;
for (int h = 0; h < cur_height; h++) {
dst_row = &dst_buf[h * dst_pitch];
src_row = &src_buf[h * 16];
uint64_t* src_row = (uint64_t*)&this->vram_ptr[this->regs[ATI_CUR_OFFSET] * 8];
dst_pitch -= 64 * 4;
for (int x = 0; x < 16; x++) {
px4 = src_row[x];
for (int p = 0; p < 4; p++, px4 >>= 2, dst_row += 4) {
switch(px4 & 3) {
case 0: // cursor color 0
for (int h = cur_height; h > 0; h--) {
for (int x = 2; x > 0; x--) {
uint64_t px = *src_row++;
for (int p = 32; p > 0; p--, px >>= 2, dst_row += 4) {
switch (px & 3) {
case 0: // cursor color 0
WRITE_DWORD_BE_A(dst_row, color0);
break;
case 1: // cursor color 1
case 1: // cursor color 1
WRITE_DWORD_BE_A(dst_row, color1);
break;
case 2: // transparent
case 2: // transparent
WRITE_DWORD_BE_A(dst_row, 0);
break;
case 3: // 1's complement of display pixel
case 3: // 1's complement of display pixel
WRITE_DWORD_BE_A(dst_row, 0x0000007F);
break;
}
}
}
dst_row += dst_pitch;
}
}
void ATIRage::get_cursor_position(int& x, int& y) {
x = extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_POSN], ATI_CUR_HORZ_POSN, ATI_CUR_HORZ_POSN_size);
x = extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_POSN], ATI_CUR_HORZ_POSN, ATI_CUR_HORZ_POSN_size) -
extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_OFF ], ATI_CUR_HORZ_OFF , ATI_CUR_HORZ_OFF_size );
y = extract_bits<uint32_t>(this->regs[ATI_CUR_HORZ_VERT_POSN], ATI_CUR_VERT_POSN, ATI_CUR_VERT_POSN_size);
}

View File

@ -74,9 +74,15 @@ void VideoCtrlBase::update_screen()
this->get_cursor_position(cursor_x, cursor_y);
}
this->display.update(
this->convert_fb_cb, this->cursor_ovl_cb,
this->cursor_on, cursor_x, cursor_y);
if (draw_fb) {
if (this->cursor_dirty) {
this->setup_hw_cursor();
this->cursor_dirty = false;
}
this->display.update(
this->convert_fb_cb, this->cursor_ovl_cb,
this->cursor_on, cursor_x, cursor_y);
}
}
void VideoCtrlBase::start_refresh_task() {

View File

@ -75,6 +75,7 @@ protected:
bool crtc_on = false;
bool blank_on = true;
bool cursor_on = false;
bool cursor_dirty = false;
int active_width; // width of the visible display area
int active_height; // height of the visible display area
int hori_total = 0;
@ -85,6 +86,7 @@ protected:
int pixel_format;
float pixel_clock;
float refresh_rate;
bool draw_fb = true;
uint32_t palette[256]; // internal DAC palette in RGBA format

View File

@ -342,7 +342,7 @@ int MachineFactory::load_boot_rom(string& rom_filepath) {
size_t file_size;
int result = 0;
uint32_t rom_load_addr;
AddressMapEntry *rom_reg;
//AddressMapEntry *rom_reg;
rom_file.open(rom_filepath, ios::in | ios::binary);
if (rom_file.fail()) {
@ -373,7 +373,7 @@ int MachineFactory::load_boot_rom(string& rom_filepath) {
MemCtrlBase* mem_ctrl = dynamic_cast<MemCtrlBase*>(
gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
if ((rom_reg = mem_ctrl->find_rom_region())) {
if ((/*rom_reg = */mem_ctrl->find_rom_region())) {
mem_ctrl->set_data(rom_load_addr, sysrom_mem, (uint32_t)file_size);
} else {
LOG_F(ERROR, "Could not locate physical ROM region!");