tgpx4: misc fixing (floating point conversions, broken REP opcode, support for rascot2 MOV2 int->ext opcode) (nw)

This commit is contained in:
angelosa 2018-03-22 01:47:55 +01:00
parent 4d22ad601e
commit 8364758817
3 changed files with 84 additions and 51 deletions

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Angelo Salese, ElSemi, Ville Linde // copyright-holders:Angelo Salese, ElSemi, Ville Linde
/***************************************************************************** /********************************************************************************
* *
* MB86235 "TGPx4" (c) Fujitsu * MB86235 "TGPx4" (c) Fujitsu
* *
@ -9,14 +9,16 @@
* TODO: * TODO:
* - rewrite ALU integer/floating point functions, use templates etc; * - rewrite ALU integer/floating point functions, use templates etc;
* - move post-opcodes outside of the execute_op() function, like increment_prp() * - move post-opcodes outside of the execute_op() function, like increment_prp()
* (needed if opcode uses fifo in/out); * (needed if opcode uses fifo in/out);
* - fifo stall shouldn't make the alu opcode to repeat; * - rewrite fifo hookups, remove them from the actual opcodes.
* - illegal delay slot on REP unsupported; * - use a phase system for the execution, like do_alu() being separated
* from control();
* - illegal delay slots unsupported, and no idea about what is supposed to happen;
* - externalize PDR / DDR (error LED flags on Model 2); * - externalize PDR / DDR (error LED flags on Model 2);
* - instruction cycles; * - instruction cycles;
* - pipeline (four instruction executed per cycle!) * - pipeline (four instruction executed per cycle!)
* *
*****************************************************************************/ ********************************************************************************/
#include "emu.h" #include "emu.h"
#include "mb86235.h" #include "mb86235.h"
@ -61,8 +63,8 @@ void mb86235_device::execute_run()
{ {
uint32_t curpc; uint32_t curpc;
curpc = m_core->cur_fifo_state.has_stalled ? m_core->cur_fifo_state.pc : m_core->pc; curpc = check_previous_op_stall() ? m_core->cur_fifo_state.pc : m_core->pc;
debugger_instruction_hook(this, curpc); debugger_instruction_hook(this, curpc);
opcode = m_direct->read_qword(curpc); opcode = m_direct->read_qword(curpc);
@ -218,6 +220,7 @@ void mb86235_device::device_start()
m_icountptr = &m_core->icount; m_icountptr = &m_core->icount;
m_core->fp0 = 0.0f; m_core->fp0 = 0.0f;
save_pointer(NAME(m_core->pr), 24);
} }
void mb86235_device::device_reset() void mb86235_device::device_reset()

View File

@ -240,6 +240,7 @@ private:
void generate_branch_target(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int type, int ef2); void generate_branch_target(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int type, int ef2);
bool has_register_clash(const opcode_desc *desc, int outreg); bool has_register_clash(const opcode_desc *desc, int outreg);
bool aluop_has_result(int aluop); bool aluop_has_result(int aluop);
bool check_previous_op_stall();
// interpreter // interpreter
void execute_op(uint32_t h, uint32_t l); void execute_op(uint32_t h, uint32_t l);
@ -274,7 +275,7 @@ private:
inline void decrement_prp(); inline void decrement_prp();
inline void zero_prp(); inline void zero_prp();
inline void set_alu_flagsd(uint32_t val); inline void set_alu_flagsd(uint32_t val);
inline void set_alu_flagsf(float val); inline void set_alu_flagsf(double val);
inline void set_alu_flagsi(int val); inline void set_alu_flagsi(int val);
inline bool get_alu_second_src(uint8_t which); inline bool get_alu_second_src(uint8_t which);
void handle_single_step_execution(); void handle_single_step_execution();

View File

@ -10,6 +10,7 @@
#include "emu.h" #include "emu.h"
#include "mb86235.h" #include "mb86235.h"
#include "debugger.h"
/********************* /*********************
* *
@ -60,6 +61,11 @@ void mb86235_device::handle_single_step_execution()
m_core->pc ++; m_core->pc ++;
} }
bool mb86235_device::check_previous_op_stall()
{
return (m_core->cur_fifo_state.has_stalled == true) && ((m_core->st & RP) == 0);
}
inline void mb86235_device::increment_pwp() inline void mb86235_device::increment_pwp()
{ {
m_core->pwp++; m_core->pwp++;
@ -97,11 +103,15 @@ inline uint32_t mb86235_device::decode_ea(uint8_t mode, uint8_t rx, uint8_t ry,
return m_core->ar[rx]; return m_core->ar[rx];
case 0x01: // ARx ++ case 0x01: // ARx ++
res = m_core->ar[rx]; res = m_core->ar[rx];
if(m_core->cur_fifo_state.has_stalled == true)
return res;
m_core->ar[rx]++; m_core->ar[rx]++;
m_core->ar[rx]&=0x3fff; m_core->ar[rx]&=0x3fff;
return res; return res;
case 0x03: // ARx + disp12 case 0x03: // ARx + disp12
res = m_core->ar[rx]; res = m_core->ar[rx];
if(m_core->cur_fifo_state.has_stalled == true)
return res;
m_core->ar[rx]+=disp; m_core->ar[rx]+=disp;
m_core->ar[rx]&=0x3fff; m_core->ar[rx]&=0x3fff;
return res; return res;
@ -109,11 +119,15 @@ inline uint32_t mb86235_device::decode_ea(uint8_t mode, uint8_t rx, uint8_t ry,
return m_core->ar[rx]+m_core->ar[ry]; return m_core->ar[rx]+m_core->ar[ry];
case 0x05: // ARx + ARy++ case 0x05: // ARx + ARy++
res = m_core->ar[ry]; res = m_core->ar[ry];
if(m_core->cur_fifo_state.has_stalled == true)
return res;
m_core->ar[ry]++; m_core->ar[ry]++;
m_core->ar[ry]&=0x3fff; m_core->ar[ry]&=0x3fff;
return m_core->ar[rx]+res; return m_core->ar[rx]+res;
case 0x07: // ARx + (ARy + disp12) case 0x07: // ARx + (ARy + disp12)
res = m_core->ar[ry]; res = m_core->ar[ry];
if(m_core->cur_fifo_state.has_stalled == true)
return res;
m_core->ar[ry]+=disp; m_core->ar[ry]+=disp;
m_core->ar[ry]&=0x3fff; m_core->ar[ry]&=0x3fff;
return m_core->ar[rx]+res; return m_core->ar[rx]+res;
@ -197,7 +211,7 @@ inline void mb86235_device::set_alu_flagsd(uint32_t val)
if(val==0) FSET(AZ); if(val==0) FSET(AZ);
} }
inline void mb86235_device::set_alu_flagsf(float val) inline void mb86235_device::set_alu_flagsf(double val)
{ {
FCLR(AN|AZ); FCLR(AN|AZ);
if(val<0.0) FSET(AN); if(val<0.0) FSET(AN);
@ -228,8 +242,8 @@ inline uint32_t mb86235_device::get_prx(uint8_t which)
inline uint32_t mb86235_device::get_constfloat(uint8_t which) inline uint32_t mb86235_device::get_constfloat(uint8_t which)
{ {
const float float_table[8] = { -1.0, 0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 5.0 }; const double float_table[8] = { -1.0, 0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 5.0 };
return (uint32_t)float_table[which & 7]; return f2u(float_table[which & 7]);
} }
inline uint32_t mb86235_device::get_constint(uint8_t which) inline uint32_t mb86235_device::get_constint(uint8_t which)
@ -313,9 +327,9 @@ inline void mb86235_device::decode_aluop(uint8_t opcode, uint32_t src1, uint32_t
case 0x02: // FSUB case 0x02: // FSUB
case 0x03: // FSUBZ case 0x03: // FSUBZ
{ {
float f1 = (float)src1; double f1 = u2f(src1);
float f2 = (float)src2; double f2 = u2f(src2);
float d; double d;
if(opcode & 2) if(opcode & 2)
d = f2-f1; d = f2-f1;
@ -328,34 +342,37 @@ inline void mb86235_device::decode_aluop(uint8_t opcode, uint32_t src1, uint32_t
if(d < 0.0) if(d < 0.0)
{ {
FSET(ZC); FSET(ZC);
d = 0.0f; d = 0.0;
} }
} }
set_alu_flagsf(d); set_alu_flagsf(d);
set_alureg(dst_which,d); set_alureg(dst_which,f2u(d));
break; break;
} }
case 0x04: // FCMP case 0x04: // FCMP
case 0x06: // FABC case 0x06: // FABC
{ {
float f1 = (float)src1; double f1 = u2f(src1);
float f2 = (float)src2; double f2 = u2f(src2);
float d; double d;
if(opcode & 2) if(opcode & 2)
d = fabs(f2)-fabs(f1); d = fabs(f2)-fabs(f1);
else else
d = f2-f1; d = f2-f1;
set_alu_flagsf(d); set_alu_flagsf(d);
break; break;
} }
case 0x05: // FABS case 0x05: // FABS
{ {
float d = (float)src1; double d = u2f(src1);
d = fabs(d); d = fabs(d);
set_alu_flagsf(d); set_alu_flagsf(d);
set_alureg(dst_which,d); set_alureg(dst_which,f2u(d));
break; break;
} }
@ -380,64 +397,64 @@ inline void mb86235_device::decode_aluop(uint8_t opcode, uint32_t src1, uint32_t
case 0x0a: // FRCP case 0x0a: // FRCP
{ {
float f = (float)src1; double f = u2f(src1);
FCLR(ZD); FCLR(ZD);
if(f == 0.0f) if(f == 0.0f)
FSET(ZD); FSET(ZD);
f = 1.0/f; f = 1.0/f;
set_alu_flagsf(f); set_alu_flagsf(f);
set_alureg(dst_which,f); set_alureg(dst_which,f2u(f));
break; break;
} }
case 0x0b: // FRSQ case 0x0b: // FRSQ
{ {
float f = (float)src1; double f = u2f(src1);
FCLR(NR); FCLR(NR);
if(f <= 0.0f) if(f <= 0.0f)
FSET(NR); FSET(NR);
f = 1.0/sqrtf(f); f = 1.0/sqrtf(f);
set_alu_flagsf(f); set_alu_flagsf(f);
set_alureg(dst_which,f); set_alureg(dst_which,f2u(f));
break; break;
} }
case 0x0c: // FLOG case 0x0c: // FLOG
{ {
float f = (float)src1; double f = u2f(src1);
FCLR(IL); FCLR(IL);
if(f <= 0.0f) if(f <= 0.0f)
FSET(IL); FSET(IL);
f = log(f)/0.301030f; // log2 f = log(f)/0.301030; // log2
set_alu_flagsf(f); set_alu_flagsf(f);
set_alureg(dst_which,f); set_alureg(dst_which,f2u(f));
break; break;
} }
case 0x0d: // CIF case 0x0d: // CIF
{ {
int v = (((int)src1) << 0) >> 0; int v = (int)src1;
float f = (float)v; double f = u2f(v);
set_alu_flagsf(f); set_alu_flagsf(f);
set_alureg(dst_which,f); set_alureg(dst_which,f2u(f));
break; break;
} }
case 0x0e: // CFI case 0x0e: // CFI
{ {
float f = (float)src1; double f = u2f(src1);
int v = (int)f; int v = (int)f;
set_alu_flagsi(v); set_alu_flagsi(v);
set_alureg(dst_which,v); set_alureg(dst_which,f2u(v));
break; break;
} }
case 0x0f: // CFIB case 0x0f: // CFIB
{ {
float f = (float)src1; double f = u2f(src1);
uint32_t res; uint32_t res;
FCLR(AU); FCLR(AU);
res = (uint32_t)f; res = f2u(f);
if(f<0) if(f<0)
{ {
FSET(AU); FSET(AU);
@ -592,15 +609,15 @@ void mb86235_device::decode_mulop(bool isfmul, uint32_t src1, uint32_t src2, uin
{ {
if(isfmul == true) // FMUL if(isfmul == true) // FMUL
{ {
float f1 = (float)src1; double f1 = u2f(src1);
float f2 = (float)src2; double f2 = u2f(src2);
float res = f1*f2; double res = f1*f2;
FCLR(MD|MU|MV); FCLR(MD|MU|MV);
// TODO: MD MU MV flags // TODO: MD MU MV flags
FCLR(MN|MZ); FCLR(MN|MZ);
if(res<0.0) FSET(MN); if(res<0.0) FSET(MN);
if(res==0.0) FSET(MZ); if(res==0.0) FSET(MZ);
set_alureg(dst_which,(uint32_t)res); set_alureg(dst_which,f2u(res));
} }
else // MUL else // MUL
{ {
@ -694,8 +711,6 @@ void mb86235_device::do_alu2(uint32_t h, uint32_t l)
* *
********************/ ********************/
#include "debugger.h"
inline uint32_t mb86235_device::get_transfer_reg(uint8_t which) inline uint32_t mb86235_device::get_transfer_reg(uint8_t which)
{ {
switch(which >> 3) switch(which >> 3)
@ -741,7 +756,7 @@ inline uint32_t mb86235_device::get_transfer_reg(uint8_t which)
{ {
FSET(IFE); FSET(IFE);
m_core->cur_fifo_state.has_stalled = true; m_core->cur_fifo_state.has_stalled = true;
//if((m_core->st & RP) == 0) if((m_core->st & RP) == 0)
m_core->cur_fifo_state.pc = m_core->ppc; m_core->cur_fifo_state.pc = m_core->ppc;
//else //else
// fatalerror("check me %08x\n",m_core->ppc); // fatalerror("check me %08x\n",m_core->ppc);
@ -816,8 +831,9 @@ inline void mb86235_device::set_transfer_reg(uint8_t which, uint32_t value)
{ {
FSET(OFF); FSET(OFF);
m_core->cur_fifo_state.has_stalled = true; m_core->cur_fifo_state.has_stalled = true;
//if((m_core->st & RP) == 0) if((m_core->st & RP) == 0)
m_core->cur_fifo_state.pc = m_core->ppc; m_core->cur_fifo_state.pc = m_core->ppc;
//else //else
// fatalerror("check me (writes)"); // fatalerror("check me (writes)");
return; return;
@ -958,7 +974,7 @@ void mb86235_device::do_trans2_2(uint32_t h, uint32_t l)
switch(sdb) switch(sdb)
{ {
// reg -> reg // reg -> reg
case 0: //reg->reg case 0:
{ {
uint8_t bs = (l >> 13) & 0x1f; uint8_t bs = (l >> 13) & 0x1f;
uint8_t bd = (l >> 8) & 0xf; uint8_t bd = (l >> 8) & 0xf;
@ -1013,7 +1029,16 @@ void mb86235_device::do_trans1_2(uint32_t h, uint32_t l)
disp_offs |= 1; disp_offs |= 1;
if(sr & 0x40) if(sr & 0x40)
fatalerror("TGPx4: unimplemented int->ext sr %02x at pc=%08x\n",sr,m_core->ppc); {
if(sr == 0x58)
res = l & 0xffffff;
else
{
bool isbbus = (sr & 0x20) == 0x20;
uint32_t addr = decode_ea(l & 0xf,sr & 7,(l >> 4) & 7, (l >> 7) & 0x3fff,isbbus);
res = read_bus(isbbus,addr);
}
}
else else
res = get_transfer_reg(sr); res = get_transfer_reg(sr);
@ -1085,17 +1110,17 @@ void mb86235_device::do_trans1_3(uint32_t h, uint32_t l)
inline void mb86235_device::push_pc(uint32_t pcval) inline void mb86235_device::push_pc(uint32_t pcval)
{ {
m_core->pcs[m_core->pcp++] = pcval; m_core->pcs[m_core->pcp++] = pcval;
// m_core->pcp &= 3; m_core->pcp &= 3;
if(m_core->pcp & ~3) // if(m_core->pcp & ~3)
fatalerror("TGPx4: push_pc overflow PCP=%08x PC=%08x\n",m_core->pcp,m_core->ppc); // fatalerror("TGPx4: push_pc overflow PCP=%08x PC=%08x\n",m_core->pcp,m_core->ppc);
} }
inline uint32_t mb86235_device::pop_pc() inline uint32_t mb86235_device::pop_pc()
{ {
m_core->pcp--; m_core->pcp--;
// m_core->pcp &= 3; m_core->pcp &= 3;
if(m_core->pcp & ~3) // if(m_core->pcp & ~3)
fatalerror("TGPx4: pop_pc underflow PCP=%08x PC=%08x\n",m_core->pcp,m_core->ppc); // fatalerror("TGPx4: pop_pc underflow PCP=%08x PC=%08x\n",m_core->pcp,m_core->ppc);
return m_core->pcs[m_core->pcp]; return m_core->pcs[m_core->pcp];
} }
@ -1173,6 +1198,7 @@ void mb86235_device::do_control(uint32_t h, uint32_t l)
m_core->fifoin.num = 0; m_core->fifoin.num = 0;
FSET(IFE); FSET(IFE);
FCLR(IFF); FCLR(IFF);
m_core->cur_fifo_state.has_stalled = false;
} }
if(ef1 & 2) // clear fifo0/1 out (CLRFO) if(ef1 & 2) // clear fifo0/1 out (CLRFO)
{ {
@ -1184,6 +1210,7 @@ void mb86235_device::do_control(uint32_t h, uint32_t l)
m_core->fifoout1.num = 0; m_core->fifoout1.num = 0;
FSET(OFE); FSET(OFE);
FCLR(OFF); FCLR(OFF);
m_core->cur_fifo_state.has_stalled = false;
} }
break; break;
case 0x04: // PUSH case 0x04: // PUSH
@ -1223,6 +1250,7 @@ void mb86235_device::do_control(uint32_t h, uint32_t l)
{ {
m_core->delay_slot = true; m_core->delay_slot = true;
m_core->delay_pc = do_control_dst(l); m_core->delay_pc = do_control_dst(l);
m_core->icount--;
} }
break; break;
} }
@ -1233,6 +1261,7 @@ void mb86235_device::do_control(uint32_t h, uint32_t l)
{ {
m_core->delay_slot = true; m_core->delay_slot = true;
m_core->delay_pc = do_control_dst(l); m_core->delay_pc = do_control_dst(l);
m_core->icount--;
} }
break; break;
} }