diff options
Diffstat (limited to 'src/emu/cpu/e132xs/e132xs.c')
-rw-r--r-- | src/emu/cpu/e132xs/e132xs.c | 5606 |
1 files changed, 5606 insertions, 0 deletions
diff --git a/src/emu/cpu/e132xs/e132xs.c b/src/emu/cpu/e132xs/e132xs.c new file mode 100644 index 00000000000..022ebd372eb --- /dev/null +++ b/src/emu/cpu/e132xs/e132xs.c @@ -0,0 +1,5606 @@ +/******************************************************************** + Hyperstone cpu emulator + written by Pierpaolo Prazzoli + + All the types are compatible, but they have different IRAM size and cycles + + Hyperstone models: + + 16 bits + - E1-16T + - E1-16XT + - E1-16XS + - E1-16XSR + + 32bits + - E1-32N or E1-32T + - E1-32XN or E1-32XT + - E1-32XS + - E1-32XSR + + Hynix models: + + 16 bits + - GMS30C2116 + - GMS30C2216 + + 32bits + - GMS30C2132 + - GMS30C2232 + + TODO: + - some wrong cycle counts + + CHANGELOG: + + Pierpaolo Prazzoli + - Fixed LDxx.N/P/S opcodes not to increment the destination register when + it's the same as the source or "next source" one. + + Pierpaolo Prazzoli + - Removed nested delays + - Added better delay branch support + - Fixed PC seen by a delay instruction, because a delay instruction + should use the delayed PC (thus allowing the execution of software + opcodes too) + + Tomasz Slanina + - Fixed delayed branching for delay instructions longer than 2 bytes + + Pierpaolo Prazzoli + - Added and fixed Timer without hack + + Tomasz Slanina + - Fixed MULU/MULS + - Fixed Carry in ADDC/SUBC + + Pierpaolo Prazzoli + - Fixed software opcodes used as delay instructions + - Added nested delays + + Tomasz Slanina + - Added "undefined" C flag to shift left instructions + + Pierpaolo Prazzoli + - Added interrupts-block for delay instructions + - Fixed get_emu_code_addr + - Added LDW.S and STW.S instructions + - Fixed floating point opcodes + + Tomasz Slanina + - interrputs after call and before frame are prohibited now + - emulation of FCR register + - Floating point opcodes (preliminary) + - Fixed stack addressing in RET/FRAME opcodes + - Fixed bug in SET_RS macro + - Fixed bug in return opcode (S flag) + - Added C/N flags calculation in add/adc/addi/adds/addsi and some shift opcodes + - Added writeback to ROL + - Fixed ROL/SAR/SARD/SHR/SHRD/SHL/SHLD opcode decoding (Local/Global regs) + - Fixed I and T flag in RET opcode + - Fixed XX/XM opcodes + - Fixed MOV opcode, when RD = PC + - Fixed execute_trap() + - Fixed ST opcodes, when when RS = SR + - Added interrupts + - Fixed I/O addressing + + Pierpaolo Prazzoli + - Fixed fetch + - Fixed decode of hyperstone_xm opcode + - Fixed 7 bits difference number in FRAME / RET instructions + - Some debbugger fixes + - Added generic registers decode function + - Some other little fixes. + + MooglyGuy 29/03/2004 + - Changed MOVI to use unsigned values instead of signed, correcting + an ugly glitch when loading 32-bit immediates. + Pierpaolo Prazzoli + - Same fix in get_const + + MooglyGuy - 02/27/04 + - Fixed delayed branching + - const_val for CALL should always have bit 0 clear + + Pierpaolo Prazzoli - 02/25/04 + - Fixed some wrong addresses to address local registers instead of memory + - Fixed FRAME and RET instruction + - Added preliminary I/O space + - Fixed some load / store instructions + + Pierpaolo Prazzoli - 02/20/04 + - Added execute_exception function + - Added FL == 0 always interpreted as 16 + + Pierpaolo Prazzoli - 02/19/04 + - Changed the reset to use the execute_trap(reset) which should be right to set + the initiale state of the cpu + - Added Trace exception + - Set of T flag in RET instruction + - Set I flag in interrupts entries and resetted by a RET instruction + - Added correct set instruction for SR + + Pierpaolo Prazzoli - 10/26/03 + - Changed get_lrconst to get_const and changed it to use the removed GET_CONST_RR + macro. + - Removed the High flag used in some opcodes, it should be used only in + MOV and MOVI instruction. + - Fixed MOV and MOVI instruction. + - Set to 1 FP is SR register at reset. + (From the doc: A Call, Trap or Software instruction increments the FP and sets FL + to 6, thus creating a new stack frame with the length of 6 registers). + + MooglyGuy - 10/25/03 + - Fixed CALL enough that it at least jumps to the right address, no word + yet as to whether or not it's working enough to return. + - Added get_lrconst() to get the const value for the CALL operand, since + apparently using immediate_value() was wrong. The code is ugly, but it + works properly. Vampire 1/2 now gets far enough to try to test its RAM. + - Just from looking at it, CALL apparently doesn't frame properly. I'm not + sure about FRAME, but perhaps it doesn't work properly - I'm not entirely + positive. The return address when vamphalf's memory check routine is + called at FFFFFD7E is stored in register L8, and then the RET instruction + at the end of the routine uses L1 as the return address, so that might + provide some clues as to how it works. + - I'd almost be willing to bet money that there's no framing at all since + the values in L0 - L15 as displayed by the debugger would change during a + CALL or FRAME operation. I'll look when I'm in the mood. + - The mood struck me, and I took a look at SET_L_REG and GET_L_REG. + Apparently no matter what the current frame pointer is they'll always use + local_regs[0] through local_regs[15]. + + MooglyGuy - 08/20/03 + - Added H flag support for MOV and MOVI + - Changed init routine to set S flag on boot. Apparently the CPU defaults to + supervisor mode as opposed to user mode when it powers on, as shown by the + vamphalf power-on routines. Makes sense, too, since if the machine booted + in user mode, it would be impossible to get into supervisor mode. + + Pierpaolo Prazzoli - 08/19/03 + - Added check for D_BIT and S_BIT where PC or SR must or must not be denoted. + (movd, divu, divs, ldxx1, ldxx2, stxx1, stxx2, mulu, muls, set, mul + call, chk) + + MooglyGuy - 08/17/03 + - Working on support for H flag, nothing quite done yet + - Added trap Range Error for CHK PC, PC + - Fixed relative jumps, they have to be taken from the opcode following the + jump minstead of the jump opcode itself. + + Pierpaolo Prazzoli - 08/17/03 + - Fixed get_pcrel() when OP & 0x80 is set. + - Decremented PC by 2 also in MOV, ADD, ADDI, SUM, SUB and added the check if + D_BIT is not set. (when pc is changed they are implicit branch) + + MooglyGuy - 08/17/03 + - Implemented a crude hack to set FL in the SR to 6, since according to the docs + that's supposed to happen each time a trap occurs, apparently including when + the processor starts up. The 3rd opcode executed in vamphalf checks to see if + the FL flag in SR 6, so it's apparently the "correct" behaviour despite the + docs not saying anything on it. If FL is not 6, the branch falls through and + encounters a CHK PC, L2, which at that point will always throw a range trap. + The range trap vector contains 00000000 (CHK PC, PC), which according to the + docs will always throw a range trap (which would effectively lock the system). + This revealed a bug: CHK PC, PC apparently does not throw a range trap, which + needs to be fixed. Now that the "correct" behaviour is hacked in with the FL + flags, it reveals yet another bug in that the branch is interpreted as being + +0x8700. This means that the PC then wraps around to 000082B0, give or take + a few bytes. While it does indeed branch to valid code, I highly doubt that + this is the desired effect. Check for signed/unsigned relative branch, maybe? + + MooglyGuy - 08/16/03 + - Fixed the debugger at least somewhat so that it displays hex instead of decimal, + and so that it disassembles opcodes properly. + - Fixed hyperstone_execute() to increment PC *after* executing the opcode instead of + before. This is probably why vamphalf was booting to fffffff8, but executing at + fffffffa instead. + - Changed execute_trap to decrement PC by 2 so that the next opcode isn't skipped + after a trap + - Changed execute_br to decrement PC by 2 so that the next opcode isn't skipped + after a branch + - Changed hyperstone_movi to decrement PC by 2 when G0 (PC) is modified so that the + next opcode isn't skipped after a branch + - Changed hyperstone_movi to default to a UINT32 being moved into the register + as opposed to a UINT8. This is wrong, the bit width is quite likely to be + dependent on the n field in the Rimm instruction type. However, vamphalf uses + MOVI G0,[FFFF]FBAC (n=$13) since there's apparently no absolute branch opcode. + What kind of CPU is this that it doesn't have an absolute jump in its branch + instructions and you have to use an immediate MOV to do an abs. jump!? + - Replaced usage of logerror() with smf's verboselog() + +*********************************************************************/ + +#include "debugger.h" +#include "e132xs.h" +#include "osd_cpu.h" + +static UINT8 (*hyp_cpu_read_byte)(offs_t address); +static UINT16 (*hyp_cpu_read_half_word)(offs_t address); +static UINT32 (*hyp_cpu_read_word)(offs_t address); +static UINT32 (*hyp_cpu_read_io_word)(offs_t address); +static void (*hyp_cpu_write_byte)(offs_t address, UINT8 data); +static void (*hyp_cpu_write_half_word)(offs_t address, UINT16 data); +static void (*hyp_cpu_write_word)(offs_t address, UINT32 data); +static void (*hyp_cpu_write_io_word)(offs_t address, UINT32 data); +int hyp_type_16bit; + +// set C in adds/addsi/subs/sums +#define SETCARRYS 0 +#define MISSIONCRAFT_FLAGS 1 + +static int hyperstone_ICount; + +static void hyperstone_chk(void); +static void hyperstone_movd(void); +static void hyperstone_divu(void); +static void hyperstone_divs(void); +static void hyperstone_xm(void); +static void hyperstone_mask(void); +static void hyperstone_sum(void); +static void hyperstone_sums(void); +static void hyperstone_cmp(void); +static void hyperstone_mov(void); +static void hyperstone_add(void); +static void hyperstone_adds(void); +static void hyperstone_cmpb(void); +static void hyperstone_andn(void); +static void hyperstone_or(void); +static void hyperstone_xor(void); +static void hyperstone_subc(void); +static void hyperstone_not(void); +static void hyperstone_sub(void); +static void hyperstone_subs(void); +static void hyperstone_addc(void); +static void hyperstone_and(void); +static void hyperstone_neg(void); +static void hyperstone_negs(void); +static void hyperstone_cmpi(void); +static void hyperstone_movi(void); +static void hyperstone_addi(void); +static void hyperstone_addsi(void); +static void hyperstone_cmpbi(void); +static void hyperstone_andni(void); +static void hyperstone_ori(void); +static void hyperstone_xori(void); +static void hyperstone_shrdi(void); +static void hyperstone_shrd(void); +static void hyperstone_shr(void); +static void hyperstone_sardi(void); +static void hyperstone_sard(void); +static void hyperstone_sar(void); +static void hyperstone_shldi(void); +static void hyperstone_shld(void); +static void hyperstone_shl(void); +static void reserved(void); +static void hyperstone_testlz(void); +static void hyperstone_rol(void); +static void hyperstone_ldxx1(void); +static void hyperstone_ldxx2(void); +static void hyperstone_stxx1(void); +static void hyperstone_stxx2(void); +static void hyperstone_shri(void); +static void hyperstone_sari(void); +static void hyperstone_shli(void); +static void hyperstone_mulu(void); +static void hyperstone_muls(void); +static void hyperstone_set(void); +static void hyperstone_mul(void); +static void hyperstone_fadd(void); +static void hyperstone_faddd(void); +static void hyperstone_fsub(void); +static void hyperstone_fsubd(void); +static void hyperstone_fmul(void); +static void hyperstone_fmuld(void); +static void hyperstone_fdiv(void); +static void hyperstone_fdivd(void); +static void hyperstone_fcmp(void); +static void hyperstone_fcmpd(void); +static void hyperstone_fcmpu(void); +static void hyperstone_fcmpud(void); +static void hyperstone_fcvt(void); +static void hyperstone_fcvtd(void); +static void hyperstone_extend(void); +static void hyperstone_do(void); +static void hyperstone_ldwr(void); +static void hyperstone_lddr(void); +static void hyperstone_ldwp(void); +static void hyperstone_lddp(void); +static void hyperstone_stwr(void); +static void hyperstone_stdr(void); +static void hyperstone_stwp(void); +static void hyperstone_stdp(void); +static void hyperstone_dbv(void); +static void hyperstone_dbnv(void); +static void hyperstone_dbe(void); +static void hyperstone_dbne(void); +static void hyperstone_dbc(void); +static void hyperstone_dbnc(void); +static void hyperstone_dbse(void); +static void hyperstone_dbht(void); +static void hyperstone_dbn(void); +static void hyperstone_dbnn(void); +static void hyperstone_dble(void); +static void hyperstone_dbgt(void); +static void hyperstone_dbr(void); +static void hyperstone_frame(void); +static void hyperstone_call(void); +static void hyperstone_bv(void); +static void hyperstone_bnv(void); +static void hyperstone_be(void); +static void hyperstone_bne(void); +static void hyperstone_bc(void); +static void hyperstone_bnc(void); +static void hyperstone_bse(void); +static void hyperstone_bht(void); +static void hyperstone_bn(void); +static void hyperstone_bnn(void); +static void hyperstone_ble(void); +static void hyperstone_bgt(void); +static void hyperstone_br(void); +static void hyperstone_trap(void); + +/* Registers */ + +enum +{ + E132XS_PC = 1, + E132XS_SR, + E132XS_FER, + E132XS_G3, + E132XS_G4, + E132XS_G5, + E132XS_G6, + E132XS_G7, + E132XS_G8, + E132XS_G9, + E132XS_G10, + E132XS_G11, + E132XS_G12, + E132XS_G13, + E132XS_G14, + E132XS_G15, + E132XS_G16, + E132XS_G17, + E132XS_SP, + E132XS_UB, + E132XS_BCR, + E132XS_TPR, + E132XS_TCR, + E132XS_TR, + E132XS_WCR, + E132XS_ISR, + E132XS_FCR, + E132XS_MCR, + E132XS_G28, + E132XS_G29, + E132XS_G30, + E132XS_G31, + E132XS_CL0, E132XS_CL1, E132XS_CL2, E132XS_CL3, + E132XS_CL4, E132XS_CL5, E132XS_CL6, E132XS_CL7, + E132XS_CL8, E132XS_CL9, E132XS_CL10,E132XS_CL11, + E132XS_CL12,E132XS_CL13,E132XS_CL14,E132XS_CL15, + E132XS_L0, E132XS_L1, E132XS_L2, E132XS_L3, + E132XS_L4, E132XS_L5, E132XS_L6, E132XS_L7, + E132XS_L8, E132XS_L9, E132XS_L10, E132XS_L11, + E132XS_L12, E132XS_L13, E132XS_L14, E132XS_L15, + E132XS_L16, E132XS_L17, E132XS_L18, E132XS_L19, + E132XS_L20, E132XS_L21, E132XS_L22, E132XS_L23, + E132XS_L24, E132XS_L25, E132XS_L26, E132XS_L27, + E132XS_L28, E132XS_L29, E132XS_L30, E132XS_L31, + E132XS_L32, E132XS_L33, E132XS_L34, E132XS_L35, + E132XS_L36, E132XS_L37, E132XS_L38, E132XS_L39, + E132XS_L40, E132XS_L41, E132XS_L42, E132XS_L43, + E132XS_L44, E132XS_L45, E132XS_L46, E132XS_L47, + E132XS_L48, E132XS_L49, E132XS_L50, E132XS_L51, + E132XS_L52, E132XS_L53, E132XS_L54, E132XS_L55, + E132XS_L56, E132XS_L57, E132XS_L58, E132XS_L59, + E132XS_L60, E132XS_L61, E132XS_L62, E132XS_L63 +}; + + +/* Delay information */ +struct _delay +{ + INT32 delay_cmd; + UINT32 delay_pc; +}; + +/* Internal registers */ +typedef struct +{ + UINT32 global_regs[32]; + UINT32 local_regs[64]; + + /* internal stuff */ + UINT32 ppc; // previous pc + UINT16 op; // opcode + UINT32 trap_entry; // entry point to get trap address + + UINT8 n; + INT32 delay_timer; + int timer_clocks; + + struct _delay delay; + + int (*irq_callback)(int irqline); + + INT32 h_clear; + INT32 instruction_length; + INT32 intblock; + +} hyperstone_regs; + +static hyperstone_regs hyperstone; + +static struct regs_decode +{ + UINT8 src, dst; // destination and source register code + UINT32 src_value; // current source register value + UINT32 next_src_value; // current next source register value + UINT32 dst_value; // current destination register value + UINT32 next_dst_value; // current next destination register value + UINT8 sub_type; // sub type opcode (for DD and X_CODE bits) + union + { + UINT32 u; + INT32 s; + } extra; // extra value such as immediate value, const, pcrel, ... + void (*set_src_register)(UINT8 reg, UINT32 data); // set local / global source register + void (*set_dst_register)(UINT8 reg, UINT32 data); // set local / global destination register + UINT8 src_is_pc; + UINT8 dst_is_pc; + UINT8 src_is_sr; + UINT8 dst_is_sr; + UINT8 same_src_dst; + UINT8 same_src_dstf; + UINT8 same_srcf_dst; +} current_regs; + +#define SREG current_regs.src_value +#define SREGF current_regs.next_src_value +#define DREG current_regs.dst_value +#define DREGF current_regs.next_dst_value +#define EXTRA_U current_regs.extra.u +#define EXTRA_S current_regs.extra.s + +#define SET_SREG( _data_ ) (*current_regs.set_src_register)(current_regs.src, _data_) +#define SET_SREGF( _data_ ) (*current_regs.set_src_register)(current_regs.src + 1, _data_) +#define SET_DREG( _data_ ) (*current_regs.set_dst_register)(current_regs.dst, _data_) +#define SET_DREGF( _data_ ) (*current_regs.set_dst_register)(current_regs.dst + 1, _data_) + +#define SRC_IS_PC current_regs.src_is_pc +#define DST_IS_PC current_regs.dst_is_pc +#define SRC_IS_SR current_regs.src_is_sr +#define DST_IS_SR current_regs.dst_is_sr +#define SAME_SRC_DST current_regs.same_src_dst +#define SAME_SRC_DSTF current_regs.same_src_dstf +#define SAME_SRCF_DST current_regs.same_srcf_dst + +#if (HAS_E116T || HAS_E116XT || HAS_E116XS || HAS_E116XSR || HAS_GMS30C2116 || HAS_GMS30C2216) +static UINT32 program_read_dword_16be(offs_t address) +{ + return (program_read_word_16be(address & ~1) << 16) | program_read_word_16be((address & ~1) + 2); +} + +static void program_write_dword_16be(offs_t address, UINT32 data) +{ + program_write_word_16be(address & ~1, (data & 0xffff0000)>>16); + program_write_word_16be((address & ~1)+2, data & 0xffff); +} + +static UINT32 io_read_dword_16be(offs_t address) +{ + return (io_read_word_16be(address & ~1)<< 16) | io_read_word_16be((address & ~1) + 2); +} + +static void io_write_dword_16be(offs_t address, UINT32 data) +{ + io_write_word_16be(address & ~1, (data & 0xffff0000)>>16); + io_write_word_16be((address & ~1)+2, data & 0xffff); +} +#endif + + +/* Opcodes table */ +static void (*hyperstone_op[0x100])(void) = { + hyperstone_chk, hyperstone_chk, hyperstone_chk, hyperstone_chk, /* CHK - CHKZ - NOP */ + hyperstone_movd, hyperstone_movd, hyperstone_movd, hyperstone_movd, /* MOVD - RET */ + hyperstone_divu, hyperstone_divu, hyperstone_divu, hyperstone_divu, /* DIVU */ + hyperstone_divs, hyperstone_divs, hyperstone_divs, hyperstone_divs, /* DIVS */ + hyperstone_xm, hyperstone_xm, hyperstone_xm, hyperstone_xm, /* XMx - XXx */ + hyperstone_mask, hyperstone_mask, hyperstone_mask, hyperstone_mask, /* MASK */ + hyperstone_sum, hyperstone_sum, hyperstone_sum, hyperstone_sum, /* SUM */ + hyperstone_sums, hyperstone_sums, hyperstone_sums, hyperstone_sums, /* SUMS */ + hyperstone_cmp, hyperstone_cmp, hyperstone_cmp, hyperstone_cmp, /* CMP */ + hyperstone_mov, hyperstone_mov, hyperstone_mov, hyperstone_mov, /* MOV */ + hyperstone_add, hyperstone_add, hyperstone_add, hyperstone_add, /* ADD */ + hyperstone_adds, hyperstone_adds, hyperstone_adds, hyperstone_adds, /* ADDS */ + hyperstone_cmpb, hyperstone_cmpb, hyperstone_cmpb, hyperstone_cmpb, /* CMPB */ + hyperstone_andn, hyperstone_andn, hyperstone_andn, hyperstone_andn, /* ANDN */ + hyperstone_or, hyperstone_or, hyperstone_or, hyperstone_or, /* OR */ + hyperstone_xor, hyperstone_xor, hyperstone_xor, hyperstone_xor, /* XOR */ + hyperstone_subc, hyperstone_subc, hyperstone_subc, hyperstone_subc, /* SUBC */ + hyperstone_not, hyperstone_not, hyperstone_not, hyperstone_not, /* NOT */ + hyperstone_sub, hyperstone_sub, hyperstone_sub, hyperstone_sub, /* SUB */ + hyperstone_subs, hyperstone_subs, hyperstone_subs, hyperstone_subs, /* SUBS */ + hyperstone_addc, hyperstone_addc, hyperstone_addc, hyperstone_addc, /* ADDC */ + hyperstone_and, hyperstone_and, hyperstone_and, hyperstone_and, /* AND */ + hyperstone_neg, hyperstone_neg, hyperstone_neg, hyperstone_neg, /* NEG */ + hyperstone_negs, hyperstone_negs, hyperstone_negs, hyperstone_negs, /* NEGS */ + hyperstone_cmpi, hyperstone_cmpi, hyperstone_cmpi, hyperstone_cmpi, /* CMPI */ + hyperstone_movi, hyperstone_movi, hyperstone_movi, hyperstone_movi, /* MOVI */ + hyperstone_addi, hyperstone_addi, hyperstone_addi, hyperstone_addi, /* ADDI */ + hyperstone_addsi,hyperstone_addsi,hyperstone_addsi, hyperstone_addsi, /* ADDSI */ + hyperstone_cmpbi,hyperstone_cmpbi,hyperstone_cmpbi, hyperstone_cmpbi, /* CMPBI */ + hyperstone_andni,hyperstone_andni,hyperstone_andni, hyperstone_andni, /* ANDNI */ + hyperstone_ori, hyperstone_ori, hyperstone_ori, hyperstone_ori, /* ORI */ + hyperstone_xori, hyperstone_xori, hyperstone_xori, hyperstone_xori, /* XORI */ + hyperstone_shrdi,hyperstone_shrdi,hyperstone_shrd, hyperstone_shr, /* SHRDI, SHRD, SHR */ + hyperstone_sardi,hyperstone_sardi,hyperstone_sard, hyperstone_sar, /* SARDI, SARD, SAR */ + hyperstone_shldi,hyperstone_shldi,hyperstone_shld, hyperstone_shl, /* SHLDI, SHLD, SHL */ + reserved, reserved, hyperstone_testlz,hyperstone_rol, /* RESERVED, TESTLZ, ROL */ + hyperstone_ldxx1,hyperstone_ldxx1,hyperstone_ldxx1, hyperstone_ldxx1, /* LDxx.D/A/IOD/IOA */ + hyperstone_ldxx2,hyperstone_ldxx2,hyperstone_ldxx2, hyperstone_ldxx2, /* LDxx.N/S */ + hyperstone_stxx1,hyperstone_stxx1,hyperstone_stxx1, hyperstone_stxx1, /* STxx.D/A/IOD/IOA */ + hyperstone_stxx2,hyperstone_stxx2,hyperstone_stxx2, hyperstone_stxx2, /* STxx.N/S */ + hyperstone_shri, hyperstone_shri, hyperstone_shri, hyperstone_shri, /* SHRI */ + hyperstone_sari, hyperstone_sari, hyperstone_sari, hyperstone_sari, /* SARI */ + hyperstone_shli, hyperstone_shli, hyperstone_shli, hyperstone_shli, /* SHLI */ + reserved, reserved, reserved, reserved, /* RESERVED */ + hyperstone_mulu, hyperstone_mulu, hyperstone_mulu, hyperstone_mulu, /* MULU */ + hyperstone_muls, hyperstone_muls, hyperstone_muls, hyperstone_muls, /* MULS */ + hyperstone_set, hyperstone_set, hyperstone_set, hyperstone_set, /* SETxx - SETADR - FETCH */ + hyperstone_mul, hyperstone_mul, hyperstone_mul, hyperstone_mul, /* MUL */ + hyperstone_fadd, hyperstone_faddd,hyperstone_fsub, hyperstone_fsubd, /* FADD, FADDD, FSUB, FSUBD */ + hyperstone_fmul, hyperstone_fmuld,hyperstone_fdiv, hyperstone_fdivd, /* FMUL, FMULD, FDIV, FDIVD */ + hyperstone_fcmp, hyperstone_fcmpd,hyperstone_fcmpu, hyperstone_fcmpud, /* FCMP, FCMPD, FCMPU, FCMPUD */ + hyperstone_fcvt, hyperstone_fcvtd,hyperstone_extend,hyperstone_do, /* FCVT, FCVTD, EXTEND, DO */ + hyperstone_ldwr, hyperstone_ldwr, hyperstone_lddr, hyperstone_lddr, /* LDW.R, LDD.R */ + hyperstone_ldwp, hyperstone_ldwp, hyperstone_lddp, hyperstone_lddp, /* LDW.P, LDD.P */ + hyperstone_stwr, hyperstone_stwr, hyperstone_stdr, hyperstone_stdr, /* STW.R, STD.R */ + hyperstone_stwp, hyperstone_stwp, hyperstone_stdp, hyperstone_stdp, /* STW.P, STD.P */ + hyperstone_dbv, hyperstone_dbnv, hyperstone_dbe, hyperstone_dbne, /* DBV, DBNV, DBE, DBNE */ + hyperstone_dbc, hyperstone_dbnc, hyperstone_dbse, hyperstone_dbht, /* DBC, DBNC, DBSE, DBHT */ + hyperstone_dbn, hyperstone_dbnn, hyperstone_dble, hyperstone_dbgt, /* DBN, DBNN, DBLE, DBGT */ + hyperstone_dbr, hyperstone_frame,hyperstone_call, hyperstone_call, /* DBR, FRAME, CALL */ + hyperstone_bv, hyperstone_bnv, hyperstone_be, hyperstone_bne, /* BV, BNV, BE, BNE */ + hyperstone_bc, hyperstone_bnc, hyperstone_bse, hyperstone_bht, /* BC, BNC, BSE, BHT */ + hyperstone_bn, hyperstone_bnn, hyperstone_ble, hyperstone_bgt, /* BN, BNN, BLE, BGT */ + hyperstone_br, hyperstone_trap, hyperstone_trap, hyperstone_trap /* BR, TRAPxx - TRAP */ +}; + +// 4Kb IRAM (On-Chip Memory) +#if (HAS_E116T || HAS_GMS30C2116) + +static ADDRESS_MAP_START( e116_4k_iram_map, ADDRESS_SPACE_PROGRAM, 16 ) + AM_RANGE(0xc0000000, 0xc0000fff) AM_RAM AM_MIRROR(0x1ffff000) +ADDRESS_MAP_END + +#endif + +#if (HAS_E132N || HAS_E132T || HAS_GMS30C2132) + +static ADDRESS_MAP_START( e132_4k_iram_map, ADDRESS_SPACE_PROGRAM, 32 ) + AM_RANGE(0xc0000000, 0xc0000fff) AM_RAM AM_MIRROR(0x1ffff000) +ADDRESS_MAP_END + +#endif + +// 8Kb IRAM (On-Chip Memory) + +#if (HAS_E116XT || HAS_GMS30C2216) + +static ADDRESS_MAP_START( e116_8k_iram_map, ADDRESS_SPACE_PROGRAM, 16 ) + AM_RANGE(0xc0000000, 0xc0001fff) AM_RAM AM_MIRROR(0x1fffe000) +ADDRESS_MAP_END + +#endif + +#if (HAS_E132XN || HAS_E132XT || HAS_GMS30C2232) + +static ADDRESS_MAP_START( e132_8k_iram_map, ADDRESS_SPACE_PROGRAM, 32 ) + AM_RANGE(0xc0000000, 0xc0001fff) AM_RAM AM_MIRROR(0x1fffe000) +ADDRESS_MAP_END + +#endif + +// 16Kb IRAM (On-Chip Memory) + +#if (HAS_E116XS || HAS_E116XSR) + +static ADDRESS_MAP_START( e116_16k_iram_map, ADDRESS_SPACE_PROGRAM, 16 ) + AM_RANGE(0xc0000000, 0xc0003fff) AM_RAM AM_MIRROR(0x1fffc000) +ADDRESS_MAP_END + +#endif + +#if (HAS_E132XS || HAS_E132XSR) + +static ADDRESS_MAP_START( e132_16k_iram_map, ADDRESS_SPACE_PROGRAM, 32 ) + AM_RANGE(0xc0000000, 0xc0003fff) AM_RAM AM_MIRROR(0x1fffc000) +ADDRESS_MAP_END + +#endif + +/* Return the entry point for a determinated trap */ +static UINT32 get_trap_addr(UINT8 trapno) +{ + UINT32 addr; + if( hyperstone.trap_entry == 0xffffff00 ) /* @ MEM3 */ + { + addr = trapno * 4; + } + else + { + addr = (63 - trapno) * 4; + } + addr |= hyperstone.trap_entry; + + return addr; +} + +/* Return the entry point for a determinated emulated code (the one for "extend" opcode is reserved) */ +static UINT32 get_emu_code_addr(UINT8 num) /* num is OP */ +{ + UINT32 addr; + if( hyperstone.trap_entry == 0xffffff00 ) /* @ MEM3 */ + { + addr = (hyperstone.trap_entry - 0x100) | ((num & 0xf) << 4); + } + else + { + addr = hyperstone.trap_entry | (0x10c | ((0xcf - num) << 4)); + } + return addr; +} + +static void hyperstone_set_trap_entry(int which) +{ + switch( which ) + { + case E132XS_ENTRY_MEM0: + hyperstone.trap_entry = 0x00000000; + break; + + case E132XS_ENTRY_MEM1: + hyperstone.trap_entry = 0x40000000; + break; + + case E132XS_ENTRY_MEM2: + hyperstone.trap_entry = 0x80000000; + break; + + case E132XS_ENTRY_MEM3: + hyperstone.trap_entry = 0xffffff00; + break; + + case E132XS_ENTRY_IRAM: + hyperstone.trap_entry = 0xc0000000; + break; + + default: + logerror("Set entry point to a reserved value: %d\n", which); + break; + } +} + +#define OP hyperstone.op + +#define PPC hyperstone.ppc //previous pc +#define PC hyperstone.global_regs[0] //Program Counter +#define SR hyperstone.global_regs[1] //Status Register +#define FER hyperstone.global_regs[2] //Floating-Point Exception Register +// 03 - 15 General Purpose Registers +// 16 - 17 Reserved +#define SP hyperstone.global_regs[18] //Stack Pointer +#define UB hyperstone.global_regs[19] //Upper Stack Bound +#define BCR hyperstone.global_regs[20] //Bus Control Register +#define TPR hyperstone.global_regs[21] //Timer Prescaler Register +#define TCR hyperstone.global_regs[22] //Timer Compare Register +#define TR hyperstone.global_regs[23] //Timer Register +#define WCR hyperstone.global_regs[24] //Watchdog Compare Register +#define ISR hyperstone.global_regs[25] //Input Status Register +#define FCR hyperstone.global_regs[26] //Function Control Register +#define MCR hyperstone.global_regs[27] //Memory Control Register +// 28 - 31 Reserved + +/* SR flags */ +#define GET_C ( SR & 0x00000001) // bit 0 //CARRY +#define GET_Z ((SR & 0x00000002)>>1) // bit 1 //ZERO +#define GET_N ((SR & 0x00000004)>>2) // bit 2 //NEGATIVE +#define GET_V ((SR & 0x00000008)>>3) // bit 3 //OVERFLOW +#define GET_M ((SR & 0x00000010)>>4) // bit 4 //CACHE-MODE +#define GET_H ((SR & 0x00000020)>>5) // bit 5 //HIGHGLOBAL +// bit 6 RESERVED (always 0) +#define GET_I ((SR & 0x00000080)>>7) // bit 7 //INTERRUPT-MODE +#define GET_FTE ((SR & 0x00001f00)>>8) // bits 12 - 8 //Floating-Point Trap Enable +#define GET_FRM ((SR & 0x00006000)>>13) // bits 14 - 13 //Floating-Point Rounding Mode +#define GET_L ((SR & 0x00008000)>>15) // bit 15 //INTERRUPT-LOCK +#define GET_T ((SR & 0x00010000)>>16) // bit 16 //TRACE-MODE +#define GET_P ((SR & 0x00020000)>>17) // bit 17 //TRACE PENDING +#define GET_S ((SR & 0x00040000)>>18) // bit 18 //SUPERVISOR STATE +#define GET_ILC ((SR & 0x00180000)>>19) // bits 20 - 19 //INSTRUCTION-LENGTH +/* if FL is zero it is always interpreted as 16 */ +#define GET_FL ((SR & 0x01e00000) ? ((SR & 0x01e00000)>>21) : 16) // bits 24 - 21 //FRAME LENGTH +#define GET_FP ((SR & 0xfe000000)>>25) // bits 31 - 25 //FRAME POINTER + +#define SET_C(val) (SR = (SR & ~0x00000001) | (val)) +#define SET_Z(val) (SR = (SR & ~0x00000002) | ((val) << 1)) +#define SET_N(val) (SR = (SR & ~0x00000004) | ((val) << 2)) +#define SET_V(val) (SR = (SR & ~0x00000008) | ((val) << 3)) +#define SET_M(val) (SR = (SR & ~0x00000010) | ((val) << 4)) +#define SET_H(val) (SR = (SR & ~0x00000020) | ((val) << 5)) +#define SET_I(val) (SR = (SR & ~0x00000080) | ((val) << 7)) +#define SET_FTE(val) (SR = (SR & ~0x00001f00) | ((val) << 8)) +#define SET_FRM(val) (SR = (SR & ~0x00006000) | ((val) << 13)) +#define SET_L(val) (SR = (SR & ~0x00008000) | ((val) << 15)) +#define SET_T(val) (SR = (SR & ~0x00010000) | ((val) << 16)) +#define SET_P(val) (SR = (SR & ~0x00020000) | ((val) << 17)) +#define SET_S(val) (SR = (SR & ~0x00040000) | ((val) << 18)) +#define SET_ILC(val) (SR = (SR & ~0x00180000) | ((val) << 19)) +#define SET_FL(val) (SR = (SR & ~0x01e00000) | ((val) << 21)) +#define SET_FP(val) (SR = (SR & ~0xfe000000) | ((val) << 25)) + +#define SET_PC(val) PC = ((val) & 0xfffffffe) //PC(0) = 0 +#define SET_SP(val) SP = ((val) & 0xfffffffc) //SP(0) = SP(1) = 0 +#define SET_UB(val) UB = ((val) & 0xfffffffc) //UB(0) = UB(1) = 0 + +#define SET_LOW_SR(val) (SR = (SR & 0xffff0000) | ((val) & 0x0000ffff)) // when SR is addressed, only low 16 bits can be changed + + +#define CHECK_C(x) (SR = (SR & ~0x00000001) | (((x) & (((UINT64)1) << 32)) ? 1 : 0 )) +#define CHECK_VADD(x,y,z) (SR = (SR & ~0x00000008) | ((((x) ^ (z)) & ((y) ^ (z)) & 0x80000000) ? 8: 0)) +#define CHECK_VADD3(x,y,w,z) (SR = (SR & ~0x00000008) | ((((x) ^ (z)) & ((y) ^ (z)) & ((w) ^ (z)) & 0x80000000) ? 8: 0)) +#define CHECK_VSUB(x,y,z) (SR = (SR & ~0x00000008) | ((((z) ^ (y)) & ((y) ^ (x)) & 0x80000000) ? 8: 0)) + + +/* FER flags */ +#define GET_ACCRUED (FER & 0x0000001f) //bits 4 - 0 //Floating-Point Accrued Exceptions +#define GET_ACTUAL (FER & 0x00001f00) //bits 12 - 8 //Floating-Point Actual Exceptions +//other bits are reversed, in particular 7 - 5 for the operating system. +//the user program can only changes the above 2 flags + +static UINT32 get_global_register(UINT8 code) +{ +/* + if( code >= 16 ) + { + switch( code ) + { + case 16: + case 17: + case 28: + case 29: + case 30: + case 31: + mame_printf_debug("read _Reserved_ Global Register %d @ %08X\n",code,PC); + break; + + case BCR_REGISTER: + mame_printf_debug("read write-only BCR register @ %08X\n",PC); + return 0; + + case TPR_REGISTER: + mame_printf_debug("read write-only TPR register @ %08X\n",PC); + return 0; + + case FCR_REGISTER: + mame_printf_debug("read write-only FCR register @ %08X\n",PC); + return 0; + + case MCR_REGISTER: + mame_printf_debug("read write-only MCR register @ %08X\n",PC); + return 0; + } + } +*/ + return hyperstone.global_regs[code]; +} + +static void set_global_register(UINT8 code, UINT32 val) +{ + //TODO: add correct FER set instruction + + if( code == PC_REGISTER ) + { + SET_PC(val); + change_pc(PC); + } + else if( code == SR_REGISTER ) + { + SET_LOW_SR(val); // only a RET instruction can change the full content of SR + + SR &= ~0x40; //reserved bit 6 always zero + } + else + { + if( code != ISR_REGISTER ) + hyperstone.global_regs[code] = val; + else + logerror("Written to ISR register. PC = %08X\n", PC); + + //are these set only when privilege bit is set? + if( code >= 16 ) + { + switch( code ) + { + case 18: + SET_SP(val); + break; + + case 19: + SET_UB(val); + break; +/* + case ISR_REGISTER: + mame_printf_debug("written %08X to read-only ISR register\n",val); + break; + + case 22: +// mame_printf_debug("written %08X to TCR register\n",val); + break; + + case 23: +// mame_printf_debug("written %08X to TR register\n",val); + break; + + case 24: +// mame_printf_debug("written %08X to WCR register\n",val); + break; + + case 16: + case 17: + case 28: + case 29: + case 30: + case 31: + mame_printf_debug("written %08X to _Reserved_ Global Register %d\n",val,code); + break; + + case BCR_REGISTER: + break; +*/ + case TPR_REGISTER: + + hyperstone.n = (val & 0xff0000) >> 16; + + if(!(val & 0x80000000)) /* change immediately */ + { + hyperstone.delay_timer = 0; + hyperstone.timer_clocks = hyperstone.n + 2; + } + else + { + hyperstone.delay_timer = 1; + } + + break; +/* + case FCR_REGISTER: + switch((val & 0x3000)>>12) + { + case 0: + mame_printf_debug("IO3 interrupt mode\n"); + break; + case 1: + mame_printf_debug("IO3 timing mode\n"); + break; + case 2: + mame_printf_debug("watchdog mode\n"); + break; + case 3: + // IO3 standard mode + break; + } + break; +*/ + case MCR_REGISTER: + // bits 14..12 EntryTableMap + hyperstone_set_trap_entry((val & 0x7000) >> 12); + + break; + } + } + } +} + +static void set_local_register(UINT8 code, UINT32 val) +{ + UINT8 new_code = (code + GET_FP) % 64; + + hyperstone.local_regs[new_code] = val; +} + +#define GET_ABS_L_REG(code) hyperstone.local_regs[code] +#define SET_L_REG(code, val) set_local_register(code, val) +#define SET_ABS_L_REG(code, val) hyperstone.local_regs[code] = val +#define GET_G_REG(code) get_global_register(code) +#define SET_G_REG(code, val) set_global_register(code, val) + +#define S_BIT ((OP & 0x100) >> 8) +#define N_BIT S_BIT +#define D_BIT ((OP & 0x200) >> 9) +#define N_VALUE ((N_BIT << 4) | (OP & 0x0f)) +#define DST_CODE ((OP & 0xf0) >> 4) +#define SRC_CODE (OP & 0x0f) +#define SIGN_BIT(val) ((val & 0x80000000) >> 31) + +#define LOCAL 1 + +static void decode_source(int local, int hflag) +{ + if(local) + { + UINT8 code = current_regs.src; + current_regs.set_src_register = set_local_register; + code = (current_regs.src + GET_FP) % 64; // registers offset by frame pointer + SREG = hyperstone.local_regs[code]; + code = (current_regs.src + 1 + GET_FP) % 64; + SREGF = hyperstone.local_regs[code]; + } + else + { + current_regs.set_src_register = set_global_register; + + if(hflag) + current_regs.src += hflag * 16; + + SREG = hyperstone.global_regs[current_regs.src]; + + /* bound safe */ + if(current_regs.src != 15 && current_regs.src != 31) + SREGF = hyperstone.global_regs[current_regs.src + 1]; + + if(current_regs.src == PC_REGISTER) + SRC_IS_PC = 1; + else if(current_regs.src == SR_REGISTER) + SRC_IS_SR = 1; + else if( current_regs.src == BCR_REGISTER || current_regs.src == TPR_REGISTER || + current_regs.src == FCR_REGISTER || current_regs.src == MCR_REGISTER ) + { + SREG = 0; // write-only registers + } + else if( current_regs.src == ISR_REGISTER ) + mame_printf_debug("read src ISR. PC = %08X\n",PPC); + } +} + +static void decode_dest(int local, int hflag) +{ + if(local) + { + UINT8 code = current_regs.dst; + current_regs.set_dst_register = set_local_register; + code = (current_regs.dst + GET_FP) % 64; // registers offset by frame pointer + DREG = hyperstone.local_regs[code]; + code = (current_regs.dst + 1 + GET_FP) % 64; + DREGF = hyperstone.local_regs[code]; + } + else + { + current_regs.set_dst_register = set_global_register; + + if(hflag) + current_regs.dst += hflag * 16; + + DREG = hyperstone.global_regs[current_regs.dst]; + + /* bound safe */ + if(current_regs.dst != 15 && current_regs.dst != 31) + DREGF = hyperstone.global_regs[current_regs.dst + 1]; + + if(current_regs.dst == PC_REGISTER) + DST_IS_PC = 1; + else if(current_regs.dst == SR_REGISTER) + DST_IS_SR = 1; + else if( current_regs.src == ISR_REGISTER ) + mame_printf_debug("read dst ISR. PC = %08X\n",PPC); + } +} + +INLINE void decode_RR(void) +{ + current_regs.src = SRC_CODE; + current_regs.dst = DST_CODE; + decode_source(S_BIT, 0); + decode_dest(D_BIT, 0); + + if( SRC_CODE == DST_CODE && S_BIT == D_BIT ) + SAME_SRC_DST = 1; + + if( S_BIT == LOCAL && D_BIT == LOCAL ) + { + if( SRC_CODE == ((DST_CODE + 1) % 64) ) + SAME_SRC_DSTF = 1; + + if( ((SRC_CODE + 1) % 64) == DST_CODE ) + SAME_SRCF_DST = 1; + } + else if( S_BIT == 0 && D_BIT == 0 ) + { + if( SRC_CODE == (DST_CODE + 1) ) + SAME_SRC_DSTF = 1; + + if( (SRC_CODE + 1) == DST_CODE ) + SAME_SRCF_DST = 1; + } +} + +INLINE void decode_LL(void) +{ + current_regs.src = SRC_CODE; + current_regs.dst = DST_CODE; + decode_source(LOCAL, 0); + decode_dest(LOCAL, 0); + + if( SRC_CODE == DST_CODE ) + SAME_SRC_DST = 1; + + if( SRC_CODE == ((DST_CODE + 1) % 64) ) + SAME_SRC_DSTF = 1; +} + +INLINE void decode_LR(void) +{ + current_regs.src = SRC_CODE; + current_regs.dst = DST_CODE; + decode_source(S_BIT, 0); + decode_dest(LOCAL, 0); + + if( ((SRC_CODE + 1) % 64) == DST_CODE && S_BIT == LOCAL ) + SAME_SRCF_DST = 1; +} + +INLINE void check_delay_PC(void) +{ + // if PC is used in a delay instruction, the delayed PC should be used + if( hyperstone.delay.delay_cmd == DELAY_EXECUTE ) + { + PC = hyperstone.delay.delay_pc; + hyperstone.delay.delay_cmd = NO_DELAY; + } +} + +INLINE void decode_immediate(void) +{ + switch( N_VALUE ) + { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: + case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: + EXTRA_U = N_VALUE; + break; + + case 17: + hyperstone.instruction_length = 3; + EXTRA_U = (READ_OP(PC) << 16) | READ_OP(PC + 2); + PC += 4; + break; + + case 18: + hyperstone.instruction_length = 2; + EXTRA_U = READ_OP(PC); + PC += 2; + break; + + case 19: + hyperstone.instruction_length = 2; + EXTRA_U = 0xffff0000 | READ_OP(PC); + PC += 2; + break; + + case 20: + EXTRA_U = 32; // bit 5 = 1, others = 0 + break; + + case 21: + EXTRA_U = 64; // bit 6 = 1, others = 0 + break; + + case 22: + EXTRA_U = 128; // bit 7 = 1, others = 0 + break; + + case 23: + EXTRA_U = 0x80000000; // bit 31 = 1, others = 0 (2 at the power of 31) + break; + + case 24: + EXTRA_U = -8; + break; + + case 25: + EXTRA_U = -7; + break; + + case 26: + EXTRA_U = -6; + break; + + case 27: + EXTRA_U = -5; + break; + + case 28: + EXTRA_U = -4; + break; + + case 29: + EXTRA_U = -3; + break; + + case 30: + EXTRA_U = -2; + break; + + case 31: + EXTRA_U = -1; + break; + } +} + +INLINE void decode_const(void) +{ + UINT16 imm_1 = READ_OP(PC); + + PC += 2; + hyperstone.instruction_length = 2; + + if( E_BIT(imm_1) ) + { + UINT16 imm_2 = READ_OP(PC); + + PC += 2; + hyperstone.instruction_length = 3; + + EXTRA_S = imm_2; + EXTRA_S |= ((imm_1 & 0x3fff) << 16); + + if( S_BIT_CONST(imm_1) ) + { + EXTRA_S |= 0xc0000000; + } + } + else + { + EXTRA_S = imm_1 & 0x3fff; + + if( S_BIT_CONST(imm_1) ) + { + EXTRA_S |= 0xffffc000; + } + } +} + +INLINE void decode_pcrel(void) +{ + if( OP & 0x80 ) + { + UINT16 next = READ_OP(PC); + + PC += 2; + hyperstone.instruction_length = 2; + + EXTRA_S = (OP & 0x7f) << 16; + EXTRA_S |= (next & 0xfffe); + + if( next & 1 ) + EXTRA_S |= 0xff800000; + } + else + { + EXTRA_S = OP & 0x7e; + + if( OP & 1 ) + EXTRA_S |= 0xffffff80; + } +} + +INLINE void decode_dis(void) +{ + UINT16 next_1 = READ_OP(PC); + + PC += 2; + hyperstone.instruction_length = 2; + + current_regs.sub_type = DD(next_1); + + if( E_BIT(next_1) ) + { + UINT16 next_2 = READ_OP(PC); + + PC += 2; + hyperstone.instruction_length = 3; + + EXTRA_S = next_2; + EXTRA_S |= ((next_1 & 0xfff) << 16); + + if( S_BIT_CONST(next_1) ) + { + EXTRA_S |= 0xf0000000; + } + } + else + { + EXTRA_S = next_1 & 0xfff; + + if( S_BIT_CONST(next_1) ) + { + EXTRA_S |= 0xfffff000; + } + } +} + +INLINE void decode_lim(void) +{ + UINT32 next = READ_OP(PC); + PC += 2; + hyperstone.instruction_length = 2; + + current_regs.sub_type = X_CODE(next); + + if( E_BIT(next) ) + { + EXTRA_U = ((next & 0xfff) << 16) | READ_OP(PC); + PC += 2; + hyperstone.instruction_length = 3; + } + else + { + EXTRA_U = next & 0xfff; + } +} + +/* used in the jumptable */ +INLINE void RRdecode(void) +{ + check_delay_PC(); + decode_RR(); +} + +INLINE void RRlimdecode(void) +{ + decode_lim(); + check_delay_PC(); + decode_RR(); +} + +INLINE void RRconstdecode(void) +{ + decode_const(); + check_delay_PC(); + decode_RR(); +} + +INLINE void RRdisdecode(void) +{ + decode_dis(); + check_delay_PC(); + decode_RR(); +} + +INLINE void RRdecodewithHflag(void) +{ + check_delay_PC(); + current_regs.src = SRC_CODE; + current_regs.dst = DST_CODE; + decode_source(S_BIT, GET_H); + decode_dest(D_BIT, GET_H); + + if(GET_H) + if(S_BIT == 0 && D_BIT == 0) + popmessage("MOV with hflag and 2 GRegs! PC = %08X\n",PPC); +} + +INLINE void Rimmdecode(void) +{ + decode_immediate(); + check_delay_PC(); + current_regs.dst = DST_CODE; + decode_dest(D_BIT, 0); +} + +INLINE void Rndecode(void) +{ + check_delay_PC(); + current_regs.dst = DST_CODE; + decode_dest(D_BIT, 0); +} + +INLINE void RimmdecodewithHflag(void) +{ + decode_immediate(); + check_delay_PC(); + current_regs.dst = DST_CODE; + decode_dest(D_BIT, GET_H); +} + +INLINE void Lndecode(void) +{ + check_delay_PC(); + current_regs.dst = DST_CODE; + decode_dest(LOCAL, 0); +} + +INLINE void LLdecode(void) +{ + check_delay_PC(); + decode_LL(); +} + +INLINE void LLextdecode(void) +{ + hyperstone.instruction_length = 2; + EXTRA_U = READ_OP(PC); + PC += 2; + check_delay_PC(); + decode_LL(); +} + +INLINE void LRdecode(void) +{ + check_delay_PC(); + decode_LR(); +} + +INLINE void LRconstdecode(void) +{ + decode_const(); + check_delay_PC(); + decode_LR(); +} + +INLINE void PCreldecode(void) +{ + decode_pcrel(); + check_delay_PC(); +} + +INLINE void PCadrdecode(void) +{ + check_delay_PC(); +} + +INLINE void no_decode(void) +{ + +} + + +/* Decode helper table */ +static void (*hyperstone_decode[0x100])(void) = { +/*00*/ RRdecode, RRdecode, RRdecode, RRdecode, /* CHK - CHKZ - NOP */ +/*04*/ RRdecode, RRdecode, RRdecode, RRdecode, /* MOVD - RET */ +/*08*/ RRdecode, RRdecode, RRdecode, RRdecode, /* DIVU */ +/*0c*/ RRdecode, RRdecode, RRdecode, RRdecode, /* DIVS */ +/*10*/ RRlimdecode, RRlimdecode, RRlimdecode, RRlimdecode, /* XMx - XXx */ +/*14*/ RRconstdecode, RRconstdecode, RRconstdecode, RRconstdecode, /* MASK */ +/*18*/ RRconstdecode, RRconstdecode, RRconstdecode, RRconstdecode, /* SUM */ +/*1c*/ RRconstdecode, RRconstdecode, RRconstdecode, RRconstdecode, /* SUMS */ +/*20*/ RRdecode, RRdecode, RRdecode, RRdecode, /* CMP */ +/*24*/ RRdecodewithHflag, RRdecodewithHflag, RRdecodewithHflag, RRdecodewithHflag, /* MOV */ +/*28*/ RRdecode, RRdecode, RRdecode, RRdecode, /* ADD */ +/*2c*/ RRdecode, RRdecode, RRdecode, RRdecode, /* ADDS */ +/*30*/ RRdecode, RRdecode, RRdecode, RRdecode, /* CMPB */ +/*34*/ RRdecode, RRdecode, RRdecode, RRdecode, /* ANDN */ +/*38*/ RRdecode, RRdecode, RRdecode, RRdecode, /* OR */ +/*3c*/ RRdecode, RRdecode, RRdecode, RRdecode, /* XOR */ +/*40*/ RRdecode, RRdecode, RRdecode, RRdecode, /* SUBC */ +/*44*/ RRdecode, RRdecode, RRdecode, RRdecode, /* NOT */ +/*48*/ RRdecode, RRdecode, RRdecode, RRdecode, /* SUB */ +/*4c*/ RRdecode, RRdecode, RRdecode, RRdecode, /* SUBS */ +/*50*/ RRdecode, RRdecode, RRdecode, RRdecode, /* ADDC */ +/*54*/ RRdecode, RRdecode, RRdecode, RRdecode, /* AND */ +/*58*/ RRdecode, RRdecode, RRdecode, RRdecode, /* NEG */ +/*5c*/ RRdecode, RRdecode, RRdecode, RRdecode, /* NEGS */ +/*60*/ Rimmdecode, Rimmdecode, Rimmdecode, Rimmdecode, /* CMPI */ +/*64*/ RimmdecodewithHflag, RimmdecodewithHflag, RimmdecodewithHflag, RimmdecodewithHflag, /* MOVI */ +/*68*/ Rimmdecode, Rimmdecode, Rimmdecode, Rimmdecode, /* ADDI */ +/*6c*/ Rimmdecode, Rimmdecode, Rimmdecode, Rimmdecode, /* ADDSI */ +/*70*/ Rimmdecode, Rimmdecode, Rimmdecode, Rimmdecode, /* CMPBI */ +/*74*/ Rimmdecode, Rimmdecode, Rimmdecode, Rimmdecode, /* ANDNI */ +/*78*/ Rimmdecode, Rimmdecode, Rimmdecode, Rimmdecode, /* ORI */ +/*7c*/ Rimmdecode, Rimmdecode, Rimmdecode, Rimmdecode, /* XORI */ +/*80*/ Lndecode, Lndecode, LLdecode, LLdecode, /* SHRDI, SHRD, SHR */ +/*84*/ Lndecode, Lndecode, LLdecode, LLdecode, /* SARDI, SARD, SAR */ +/*88*/ Lndecode, Lndecode, LLdecode, LLdecode, /* SHLDI, SHLD, SHL */ +/*8c*/ no_decode, no_decode, LLdecode, LLdecode, /* RESERVED, TESTLZ, ROL */ +/*90*/ RRdisdecode, RRdisdecode, RRdisdecode, RRdisdecode, /* LDxx.D/A/IOD/IOA */ +/*94*/ RRdisdecode, RRdisdecode, RRdisdecode, RRdisdecode, /* LDxx.N/S */ +/*98*/ RRdisdecode, RRdisdecode, RRdisdecode, RRdisdecode, /* STxx.D/A/IOD/IOA */ +/*9c*/ RRdisdecode, RRdisdecode, RRdisdecode, RRdisdecode, /* STxx.N/S */ +/*a0*/ Rndecode, Rndecode, Rndecode, Rndecode, /* SHRI */ +/*a4*/ Rndecode, Rndecode, Rndecode, Rndecode, /* SARI */ +/*a8*/ Rndecode, Rndecode, Rndecode, Rndecode, /* SHLI */ +/*ac*/ no_decode, no_decode, no_decode, no_decode, /* RESERVED */ +/*b0*/ RRdecode, RRdecode, RRdecode, RRdecode, /* MULU */ +/*b4*/ RRdecode, RRdecode, RRdecode, RRdecode, /* MULS */ +/*b8*/ Rndecode, Rndecode, Rndecode, Rndecode, /* SETxx - SETADR - FETCH */ +/*bc*/ RRdecode, RRdecode, RRdecode, RRdecode, /* MUL */ +/*c0*/ LLdecode, LLdecode, LLdecode, LLdecode, /* FADD, FADDD, FSUB, FSUBD */ +/*c4*/ LLdecode, LLdecode, LLdecode, LLdecode, /* FMUL, FMULD, FDIV, FDIVD */ +/*c8*/ LLdecode, LLdecode, LLdecode, LLdecode, /* FCMP, FCMPD, FCMPU, FCMPUD */ +/*cc*/ LLdecode, LLdecode, LLextdecode, LLdecode, /* FCVT, FCVTD, EXTEND, DO */ +/*d0*/ LRdecode, LRdecode, LRdecode, LRdecode, /* LDW.R, LDD.R */ +/*d4*/ LRdecode, LRdecode, LRdecode, LRdecode, /* LDW.P, LDD.P */ +/*d8*/ LRdecode, LRdecode, LRdecode, LRdecode, /* STW.R, STD.R */ +/*dc*/ LRdecode, LRdecode, LRdecode, LRdecode, /* STW.P, STD.P */ +/*e0*/ PCreldecode, PCreldecode, PCreldecode, PCreldecode, /* DBV, DBNV, DBE, DBNE */ +/*e4*/ PCreldecode, PCreldecode, PCreldecode, PCreldecode, /* DBC, DBNC, DBSE, DBHT */ +/*e8*/ PCreldecode, PCreldecode, PCreldecode, PCreldecode, /* DBN, DBNN, DBLE, DBGT */ +/*ec*/ PCreldecode, LLdecode, LRconstdecode, LRconstdecode, /* DBR, FRAME, CALL */ +/*f0*/ PCreldecode, PCreldecode, PCreldecode, PCreldecode, /* BV, BNV, BE, BNE */ +/*f4*/ PCreldecode, PCreldecode, PCreldecode, PCreldecode, /* BC, BNC, BSE, BHT */ +/*f8*/ PCreldecode, PCreldecode, PCreldecode, PCreldecode, /* BN, BNN, BLE, BGT */ +/*fc*/ PCreldecode, PCadrdecode, PCadrdecode, PCadrdecode /* BR, TRAPxx - TRAP */ +}; + +INLINE void execute_br(void) +{ + PPC = PC; + PC += EXTRA_S; + change_pc(PC); + SET_M(0); + + hyperstone_ICount -= 2; +} + +INLINE void execute_dbr(void) +{ + hyperstone.delay.delay_cmd = DELAY_TAKEN; + hyperstone.delay.delay_pc = PC + EXTRA_S; + + hyperstone.intblock = 3; +} + + +static void execute_trap(UINT32 addr) +{ + UINT8 reg; + UINT32 oldSR; + reg = GET_FP + GET_FL; + + SET_ILC(hyperstone.instruction_length & 3); + + oldSR = SR; + + SET_FL(6); + SET_FP(reg); + + SET_L_REG(0, (PC & 0xfffffffe) | GET_S); + SET_L_REG(1, oldSR); + + SET_M(0); + SET_T(0); + SET_L(1); + SET_S(1); + + PPC = PC; + PC = addr; + change_pc(PC); + + hyperstone_ICount -= 2; +} + + +static void execute_int(UINT32 addr) +{ + UINT8 reg; + UINT32 oldSR; + reg = GET_FP + GET_FL; + + SET_ILC(hyperstone.instruction_length & 3); + + oldSR = SR; + + SET_FL(2); + SET_FP(reg); + + SET_L_REG(0, (PC & 0xfffffffe) | GET_S); + SET_L_REG(1, oldSR); + + SET_M(0); + SET_T(0); + SET_L(1); + SET_S(1); + SET_I(1); + + PPC = PC; + PC = addr; + change_pc(PC); + + hyperstone_ICount -= 2; +} + +/* TODO: mask Parity Error and Extended Overflow exceptions */ +static void execute_exception(UINT32 addr) +{ + UINT8 reg; + UINT32 oldSR; + reg = GET_FP + GET_FL; + + SET_ILC(hyperstone.instruction_length & 3); + + oldSR = SR; + + SET_FP(reg); + SET_FL(2); + + SET_L_REG(0, (PC & 0xfffffffe) | GET_S); + SET_L_REG(1, oldSR); + + SET_M(0); + SET_T(0); + SET_L(1); + SET_S(1); + + PPC = PC; + PC = addr; + change_pc(PC); + + mame_printf_debug("EXCEPTION! PPC = %08X PC = %08X\n",PPC-2,PC-2); + hyperstone_ICount -= 2; +} + +static void execute_software(void) +{ + UINT8 reg; + UINT32 oldSR; + UINT32 addr; + UINT32 stack_of_dst; + + SET_ILC(1); + + addr = get_emu_code_addr((OP & 0xff00) >> 8); + reg = GET_FP + GET_FL; + + //since it's sure the register is in the register part of the stack, + //set the stack address to a value above the highest address + //that can be set by a following frame instruction + stack_of_dst = (SP & ~0xff) + 64*4 + (((GET_FP + current_regs.dst) % 64) * 4); //converted to 32bits offset + + oldSR = SR; + + SET_FL(6); + SET_FP(reg); + + SET_L_REG(0, stack_of_dst); + SET_L_REG(1, SREG); + SET_L_REG(2, SREGF); + SET_L_REG(3, (PC & 0xfffffffe) | GET_S); + SET_L_REG(4, oldSR); + + SET_M(0); + SET_T(0); + SET_L(1); + + PPC = PC; + PC = addr; + change_pc(PC); +} + + +/* + IRQ lines : + 0 - IO2 (trap 48) + 1 - IO1 (trap 49) + 2 - INT4 (trap 50) + 3 - INT3 (trap 51) + 4 - INT2 (trap 52) + 5 - INT1 (trap 53) + 6 - IO3 (trap 54) + 7 - TIMER (trap 55) +*/ +static void set_irq_line(int irqline, int state) +{ + /* Interrupt-Lock flag isn't set */ + + if(hyperstone.intblock) + return; + + if( !GET_L && state ) + { + int execint=0; + switch(irqline) + { + case 0: if( (FCR&(1<<6)) && (!(FCR&(1<<4))) ) execint=1; // IO2 + break; + case 1: if( (FCR&(1<<2)) && (!(FCR&(1<<0))) ) execint=1; // IO1 + break; + case 2: if( !(FCR&(1<<31)) ) execint=1; // int 4 + break; + case 3: if( !(FCR&(1<<30)) ) execint=1; // int 3 + break; + case 4: if( !(FCR&(1<<29)) ) execint=1; // int 2 + break; + case 5: if( !(FCR&(1<<28)) ) execint=1; // int 1 + break; + case 6: if( (FCR&(1<<10)) && (!(FCR&(1<<8))) ) execint=1; // IO3 + break; + case 7: if( !(FCR&(1<<23)) ) execint=1; // timer + break; + } +/* + if( (FCR&(1<<6)) && (!(FCR&(1<<4))) ) mame_printf_debug("IO2 en\n"); // IO2 + + if( (FCR&(1<<2)) && (!(FCR&(1<<0))) ) mame_printf_debug("IO1 en\n"); // IO1 + + if( !(FCR&(1<<31)) ) mame_printf_debug("int4 en\n"); // int 4 + + if( !(FCR&(1<<30)) ) mame_printf_debug("int3 en\n"); // int 3 + + if( !(FCR&(1<<29)) ) mame_printf_debug("int2 en\n"); // int 2 + + if( !(FCR&(1<<28)) ) mame_printf_debug("int1 en\n"); // int 1 + + if( (FCR&(1<<10)) && (!(FCR&(1<<8))) ) mame_printf_debug("IO3 en\n"); // IO3 + + // if( !(FCR&(1<<23)) ) mame_printf_debug("timer irq!\n"); // timer +*/ + if(execint) + { + execute_int(get_trap_addr(irqline + 48)); + (*hyperstone.irq_callback)(irqline); + } + } +} + +static void hyperstone_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ + state_save_register_item_array("E132XS", index, hyperstone.global_regs); + state_save_register_item_array("E132XS", index, hyperstone.local_regs); + state_save_register_item("E132XS", index, hyperstone.ppc); + state_save_register_item("E132XS", index, hyperstone.trap_entry); + state_save_register_item("E132XS", index, hyperstone.delay.delay_pc); + state_save_register_item("E132XS", index, hyperstone.op); + state_save_register_item("E132XS", index, hyperstone.n); + state_save_register_item("E132XS", index, hyperstone.h_clear); + state_save_register_item("E132XS", index, hyperstone.instruction_length); + state_save_register_item("E132XS", index, hyperstone.intblock); + state_save_register_item("E132XS", index, hyperstone.delay_timer); + state_save_register_item("E132XS", index, hyperstone.delay.delay_cmd); + state_save_register_item("E132XS", index, hyperstone.timer_clocks); + + hyperstone.irq_callback = irqcallback; +} + +#if (HAS_E116T || HAS_E116XT || HAS_E116XS || HAS_E116XSR || HAS_GMS30C2116 || HAS_GMS30C2216) +static void e116_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ + hyp_cpu_read_byte = program_read_byte_16be; + hyp_cpu_read_half_word = program_read_word_16be; + hyp_cpu_read_word = program_read_dword_16be; + hyp_cpu_read_io_word = io_read_dword_16be; + + hyp_cpu_write_byte = program_write_byte_16be; + hyp_cpu_write_half_word = program_write_word_16be; + hyp_cpu_write_word = program_write_dword_16be; + hyp_cpu_write_io_word = io_write_dword_16be; + + hyp_type_16bit = 1; + + hyperstone_init(index, clock, config, irqcallback); +} +#endif + +#if (HAS_E132N || HAS_E132T || HAS_E132XN || HAS_E132XT || HAS_E132XS || HAS_E132XSR || HAS_GMS30C2132 || HAS_GMS30C2232) +static void e132_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ + hyp_cpu_read_byte = program_read_byte_32be; + hyp_cpu_read_half_word = program_read_word_32be; + hyp_cpu_read_word = program_read_dword_32be; + hyp_cpu_read_io_word = io_read_dword_32be; + + hyp_cpu_write_byte = program_write_byte_32be; + hyp_cpu_write_half_word = program_write_word_32be; + hyp_cpu_write_word = program_write_dword_32be; + hyp_cpu_write_io_word = io_write_dword_32be; + + hyp_type_16bit = 0; + + hyperstone_init(index, clock, config, irqcallback); +} +#endif + +static void hyperstone_reset(void) +{ + //TODO: Add different reset initializations for BCR, MCR, FCR, TPR + + int (*save_irqcallback)(int); + + save_irqcallback = hyperstone.irq_callback; + memset(&hyperstone, 0, sizeof(hyperstone_regs)); + hyperstone.irq_callback = save_irqcallback; + + hyperstone.h_clear = 0; + hyperstone.instruction_length = 0; + + hyperstone_set_trap_entry(E132XS_ENTRY_MEM3); /* default entry point @ MEM3 */ + + set_global_register(BCR_REGISTER, ~0); + set_global_register(MCR_REGISTER, ~0); + set_global_register(FCR_REGISTER, ~0); + set_global_register(TPR_REGISTER, 0xc000000); + + PC = get_trap_addr(RESET); + change_pc(PC); + + SET_FP(0); + SET_FL(2); + + SET_M(0); + SET_T(0); + SET_L(1); + SET_S(1); + + SET_L_REG(0, (PC & 0xfffffffe) | GET_S); + SET_L_REG(1, SR); + + hyperstone_ICount -= 2; +} + +static void hyperstone_exit(void) +{ + // nothing to do +} + +/* Handle the timer, increasing its value after "timer_clocks" clocks and returning the new icount base that needs to be used for the next check */ +static int handle_timers(int current_icount, int previous_icount) +{ + int diff = previous_icount - current_icount; + int new_icount_base; + + if(diff >= hyperstone.timer_clocks) + { + TR++; // wrap around to 0 modulo 32 bits + + if( hyperstone.delay_timer ) + { + hyperstone.delay_timer = 0; + hyperstone.timer_clocks = hyperstone.n + 2; + } + + new_icount_base = current_icount + (diff - hyperstone.timer_clocks); + } + else + { + new_icount_base = previous_icount; + } + + if(!hyperstone.intblock) + { + if( !((TR - TCR) & 0x80000000) ) + { + /* generate a timer interrupt */ + set_irq_line(7, PULSE_LINE); + } + } + + return new_icount_base; +} + +static int hyperstone_execute(int cycles) +{ + int old_icount = cycles; + hyperstone_ICount = cycles; + + do + { + PPC = PC; /* copy PC to previous PC */ + + CALL_MAME_DEBUG; + + OP = READ_OP(PC); + + PC += 2; + + if(GET_H) + { + hyperstone.h_clear = 1; + } + + hyperstone.instruction_length = 1; + + /* clear 'current regs / flags' */ + current_regs.src = 0; + current_regs.dst = 0; + current_regs.src_value = 0; + current_regs.next_src_value = 0; + current_regs.dst_value = 0; + current_regs.next_dst_value = 0; + current_regs.sub_type = 0; + current_regs.extra.u = 0; + current_regs.extra.s = 0; + current_regs.set_src_register = NULL; + current_regs.set_dst_register = NULL; + current_regs.src_is_pc = 0; + current_regs.dst_is_pc = 0; + current_regs.src_is_sr = 0; + current_regs.dst_is_sr = 0; + current_regs.same_src_dst = 0; + current_regs.same_src_dstf = 0; + current_regs.same_srcf_dst = 0; + + /* decode current opcode details into current regs */ + hyperstone_decode[(OP & 0xff00) >> 8](); + + /* execute opcode */ + hyperstone_op[(OP & 0xff00) >> 8](); + + SET_ILC(hyperstone.instruction_length & 3); + + old_icount = handle_timers(hyperstone_ICount, old_icount); + + if(hyperstone.h_clear) + { + SET_H(0); + hyperstone.h_clear = 0; + } + + if( GET_T && GET_P && hyperstone.delay.delay_cmd == NO_DELAY ) /* Not in a Delayed Branch instructions */ + { + UINT32 addr = get_trap_addr(TRACE_EXCEPTION); + execute_exception(addr); + } + + if( hyperstone.delay.delay_cmd == DELAY_TAKEN ) + { + hyperstone.delay.delay_cmd = DELAY_EXECUTE; + } + + if(hyperstone.intblock > 0) + { + hyperstone.intblock--; + } + + } while( hyperstone_ICount > 0 ); + + return cycles - hyperstone_ICount; +} + +static void hyperstone_get_context(void *regs) +{ + /* copy the context */ + if( regs ) + *(hyperstone_regs *)regs = hyperstone; +} + +static void hyperstone_set_context(void *regs) +{ + /* copy the context */ + if (regs) + hyperstone = *(hyperstone_regs *)regs; +} + +#ifdef MAME_DEBUG +static offs_t hyperstone_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram) +{ + return dasm_hyperstone( buffer, pc, oprom, GET_H, GET_FP ); +} +#endif /* MAME_DEBUG */ + +/* Opcodes */ + +static void hyperstone_chk(void) +{ + UINT32 addr = get_trap_addr(RANGE_ERROR); + + if( SRC_IS_SR ) + { + if( DREG == 0 ) + execute_exception(addr); + } + else + { + if( SRC_IS_PC ) + { + if( DREG >= SREG ) + execute_exception(addr); + } + else + { + if( DREG > SREG ) + execute_exception(addr); + } + } + + hyperstone_ICount -= 1; +} + +static void hyperstone_movd(void) +{ + if( DST_IS_PC ) // Rd denotes PC + { + // RET instruction + + UINT8 old_s, old_l; + INT8 difference; // really it's 7 bits + + if( SRC_IS_PC || SRC_IS_SR ) + { + logerror("Denoted PC or SR in RET instruction. PC = %08X\n", PC); + } + else + { + old_s = GET_S; + old_l = GET_L; + PPC = PC; + + PC = SET_PC(SREG); + change_pc(PC); + SR = (SREGF & 0xffe00000) | ((SREG & 0x01) << 18 ) | (SREGF & 0x3ffff); + + hyperstone.instruction_length = 0; // undefined + + if( (!old_s && GET_S) || (!GET_S && !old_l && GET_L)) + { + UINT32 addr = get_trap_addr(PRIVILEGE_ERROR); + execute_exception(addr); + } + + difference = GET_FP - ((SP & 0x1fc) >> 2); + + /* convert to 8 bits */ + if(difference > 63) + difference = (INT8)(difference|0x80); + else if( difference < -64 ) + difference = difference & 0x7f; + + if( difference < 0 ) //else it's finished + { + do + { + SP -= 4; + SET_ABS_L_REG(((SP & 0xfc) >> 2), READ_W(SP)); + difference++; + + } while(difference != 0); + } + } + + //TODO: no 1! + hyperstone_ICount -= 1; + } + else if( SRC_IS_SR ) // Rd doesn't denote PC and Rs denotes SR + { + SET_DREG(0); + SET_DREGF(0); + SET_Z(1); + SET_N(0); + + hyperstone_ICount -= 2; + } + else // Rd doesn't denote PC and Rs doesn't denote SR + { + UINT64 tmp; + + SET_DREG(SREG); + SET_DREGF(SREGF); + + tmp = COMBINE_U64_U32_U32(SREG, SREGF); + SET_Z( tmp == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(SREG) ); + + hyperstone_ICount -= 2; + } +} + +static void hyperstone_divu(void) +{ + if( SAME_SRC_DST || SAME_SRC_DSTF ) + { + logerror("Denoted the same register code in hyperstone_divu instruction. PC = %08X\n", PC); + } + else + { + if( SRC_IS_PC || SRC_IS_SR ) + { + logerror("Denoted PC or SR as source register in hyperstone_divu instruction. PC = %08X\n", PC); + } + else + { + UINT64 dividend; + + dividend = COMBINE_U64_U32_U32(DREG, DREGF); + + if( SREG == 0 ) + { + //Rd//Rdf -> undefined + //Z -> undefined + //N -> undefined + UINT32 addr; + SET_V(1); + addr = get_trap_addr(RANGE_ERROR); + execute_exception(addr); + } + else + { + UINT32 quotient, remainder; + + /* TODO: add quotient overflow */ + quotient = dividend / SREG; + remainder = dividend % SREG; + + SET_DREG(remainder); + SET_DREGF(quotient); + + SET_Z( quotient == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(quotient) ); + SET_V(0); + } + } + } + + hyperstone_ICount -= 36; +} + +static void hyperstone_divs(void) +{ + if( SAME_SRC_DST || SAME_SRC_DSTF ) + { + logerror("Denoted the same register code in hyperstone_divs instruction. PC = %08X\n", PC); + } + else + { + if( SRC_IS_PC || SRC_IS_SR ) + { + logerror("Denoted PC or SR as source register in hyperstone_divs instruction. PC = %08X\n", PC); + } + else + { + INT64 dividend; + + dividend = (INT64) COMBINE_64_32_32(DREG, DREGF); + + if( SREG == 0 || (DREG & 0x80000000) ) + { + //Rd//Rdf -> undefined + //Z -> undefined + //N -> undefined + UINT32 addr; + SET_V(1); + addr = get_trap_addr(RANGE_ERROR); + execute_exception(addr); + } + else + { + INT32 quotient, remainder; + + /* TODO: add quotient overflow */ + quotient = dividend / ((INT32)(SREG)); + remainder = dividend % ((INT32)(SREG)); + + SET_DREG(remainder); + SET_DREGF(quotient); + + SET_Z( quotient == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(quotient) ); + SET_V(0); + } + } + } + + hyperstone_ICount -= 36; +} + +static void hyperstone_xm(void) +{ + if( SRC_IS_SR || DST_IS_SR || DST_IS_PC ) + { + logerror("Denoted PC or SR in hyperstone_xm. PC = %08X\n", PC); + } + else + { + switch( current_regs.sub_type ) // x_code + { + case 0: + case 1: + case 2: + case 3: + if( !SRC_IS_PC && (SREG > EXTRA_U) ) + { + UINT32 addr = get_trap_addr(RANGE_ERROR); + execute_exception(addr); + } + else if( SRC_IS_PC && (SREG >= EXTRA_U) ) + { + UINT32 addr = get_trap_addr(RANGE_ERROR); + execute_exception(addr); + } + else + { + SREG <<= current_regs.sub_type; + } + + break; + + case 4: + case 5: + case 6: + case 7: + current_regs.sub_type -= 4; + SREG <<= current_regs.sub_type; + + break; + } + + SET_DREG(SREG); + } + + hyperstone_ICount -= 1; +} + +static void hyperstone_mask(void) +{ + DREG = SREG & EXTRA_U; + + SET_DREG(DREG); + SET_Z( DREG == 0 ? 1 : 0 ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_sum(void) +{ + UINT64 tmp; + + if( SRC_IS_SR ) + SREG = GET_C; + + tmp = (UINT64)(SREG) + (UINT64)(EXTRA_U); + CHECK_C(tmp); + CHECK_VADD(SREG,EXTRA_U,tmp); + + DREG = SREG + EXTRA_U; + + SET_DREG(DREG); + + if( DST_IS_PC ) + SET_M(0); + + SET_Z( DREG == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(DREG) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_sums(void) +{ + INT32 res; + INT64 tmp; + + if( SRC_IS_SR ) + SREG = GET_C; + + tmp = (INT64)((INT32)(SREG)) + (INT64)(EXTRA_S); + CHECK_VADD(SREG,EXTRA_S,tmp); + +//#if SETCARRYS +// CHECK_C(tmp); +//#endif + + res = (INT32)(SREG) + EXTRA_S; + + SET_DREG(res); + + SET_Z( res == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(res) ); + + hyperstone_ICount -= 1; + + if( GET_V && !SRC_IS_SR ) + { + UINT32 addr = get_trap_addr(RANGE_ERROR); + execute_exception(addr); + } +} + +static void hyperstone_cmp(void) +{ + UINT64 tmp; + + if( SRC_IS_SR ) + SREG = GET_C; + + if( DREG == SREG ) + SET_Z(1); + else + SET_Z(0); + + if( (INT32) DREG < (INT32) SREG ) + SET_N(1); + else + SET_N(0); + + tmp = (UINT64)(DREG) - (UINT64)(SREG); + CHECK_VSUB(SREG,DREG,tmp); + + if( DREG < SREG ) + SET_C(1); + else + SET_C(0); + + hyperstone_ICount -= 1; +} + +static void hyperstone_mov(void) +{ + if( !GET_S && current_regs.dst >= 16 ) + { + UINT32 addr = get_trap_addr(PRIVILEGE_ERROR); + execute_exception(addr); + } + + SET_DREG(SREG); + + if( DST_IS_PC ) + SET_M(0); + + SET_Z( SREG == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(SREG) ); + + hyperstone_ICount -= 1; +} + + +static void hyperstone_add(void) +{ + UINT64 tmp; + + if( SRC_IS_SR ) + SREG = GET_C; + + tmp = (UINT64)(SREG) + (UINT64)(DREG); + CHECK_C(tmp); + CHECK_VADD(SREG,DREG,tmp); + + DREG = SREG + DREG; + SET_DREG(DREG); + + if( DST_IS_PC ) + SET_M(0); + + SET_Z( DREG == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(DREG) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_adds(void) +{ + INT32 res; + INT64 tmp; + + if( SRC_IS_SR ) + SREG = GET_C; + + tmp = (INT64)((INT32)(SREG)) + (INT64)((INT32)(DREG)); + + CHECK_VADD(SREG,DREG,tmp); + +//#if SETCARRYS +// CHECK_C(tmp); +//#endif + + res = (INT32)(SREG) + (INT32)(DREG); + + SET_DREG(res); + SET_Z( res == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(res) ); + + hyperstone_ICount -= 1; + + if( GET_V ) + { + UINT32 addr = get_trap_addr(RANGE_ERROR); + execute_exception(addr); + } +} + +static void hyperstone_cmpb(void) +{ + SET_Z( (DREG & SREG) == 0 ? 1 : 0 ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_andn(void) +{ + DREG = DREG & ~SREG; + + SET_DREG(DREG); + SET_Z( DREG == 0 ? 1 : 0 ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_or(void) +{ + DREG = DREG | SREG; + + SET_DREG(DREG); + SET_Z( DREG == 0 ? 1 : 0 ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_xor(void) +{ + DREG = DREG ^ SREG; + + SET_DREG(DREG); + SET_Z( DREG == 0 ? 1 : 0 ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_subc(void) +{ + UINT64 tmp; + + if( SRC_IS_SR ) + { + tmp = (UINT64)(DREG) - (UINT64)(GET_C); + CHECK_VSUB(GET_C,DREG,tmp); + } + else + { + tmp = (UINT64)(DREG) - ((UINT64)(SREG) + (UINT64)(GET_C)); + //CHECK! + CHECK_VSUB(SREG + GET_C,DREG,tmp); + } + + + if( SRC_IS_SR ) + { + DREG = DREG - GET_C; + } + else + { + DREG = DREG - (SREG + GET_C); + } + + CHECK_C(tmp); + + SET_DREG(DREG); + + SET_Z( GET_Z & (DREG == 0 ? 1 : 0) ); + SET_N( SIGN_BIT(DREG) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_not(void) +{ + SET_DREG(~SREG); + SET_Z( ~SREG == 0 ? 1 : 0 ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_sub(void) +{ + UINT64 tmp; + + if( SRC_IS_SR ) + SREG = GET_C; + + tmp = (UINT64)(DREG) - (UINT64)(SREG); + CHECK_C(tmp); + CHECK_VSUB(SREG,DREG,tmp); + + DREG = DREG - SREG; + SET_DREG(DREG); + + if( DST_IS_PC ) + SET_M(0); + + SET_Z( DREG == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(DREG) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_subs(void) +{ + INT32 res; + INT64 tmp; + + if( SRC_IS_SR ) + SREG = GET_C; + + tmp = (INT64)((INT32)(DREG)) - (INT64)((INT32)(SREG)); + +//#ifdef SETCARRYS +// CHECK_C(tmp); +//#endif + + CHECK_VSUB(SREG,DREG,tmp); + + res = (INT32)(DREG) - (INT32)(SREG); + + SET_DREG(res); + + SET_Z( res == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(res) ); + + hyperstone_ICount -= 1; + + if( GET_V ) + { + UINT32 addr = get_trap_addr(RANGE_ERROR); + execute_exception(addr); + } +} + +static void hyperstone_addc(void) +{ + UINT64 tmp; + + if( SRC_IS_SR ) + { + tmp = (UINT64)(DREG) + (UINT64)(GET_C); + CHECK_VADD(DREG,GET_C,tmp); + } + else + { + tmp = (UINT64)(SREG) + (UINT64)(DREG) + (UINT64)(GET_C); + + //CHECK! + //CHECK_VADD1: V = (DREG == 0x7FFF) && (C == 1); + //OVERFLOW = CHECK_VADD1(DREG, C, DREG+C) | CHECK_VADD(SREG, DREG+C, SREG+DREG+C) + /* check if DREG + GET_C overflows */ +// if( (DREG == 0x7FFFFFFF) && (GET_C == 1) ) +// SET_V(1); +// else +// CHECK_VADD(SREG,DREG + GET_C,tmp); + + CHECK_VADD3(SREG,DREG,GET_C,tmp); + } + + + + if( SRC_IS_SR ) + DREG = DREG + GET_C; + else + DREG = SREG + DREG + GET_C; + + CHECK_C(tmp); + + SET_DREG(DREG); + SET_Z( GET_Z & (DREG == 0 ? 1 : 0) ); + SET_N( SIGN_BIT(DREG) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_and(void) +{ + DREG = DREG & SREG; + + SET_DREG(DREG); + SET_Z( DREG == 0 ? 1 : 0 ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_neg(void) +{ + UINT64 tmp; + + if( SRC_IS_SR ) + SREG = GET_C; + + tmp = -(UINT64)(SREG); + CHECK_C(tmp); + CHECK_VSUB(SREG,0,tmp); + + DREG = -SREG; + + SET_DREG(DREG); + + SET_Z( DREG == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(DREG) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_negs(void) +{ + INT32 res; + INT64 tmp; + + if( SRC_IS_SR ) + SREG = GET_C; + + tmp = -(INT64)((INT32)(SREG)); + CHECK_VSUB(SREG,0,tmp); + +//#if SETCARRYS +// CHECK_C(tmp); +//#endif + + res = -(INT32)(SREG); + + SET_DREG(res); + + SET_Z( res == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(res) ); + + + hyperstone_ICount -= 1; + + if( GET_V && !SRC_IS_SR ) //trap doesn't occur when source is SR + { + UINT32 addr = get_trap_addr(RANGE_ERROR); + execute_exception(addr); + } +} + +static void hyperstone_cmpi(void) +{ + UINT64 tmp; + + tmp = (UINT64)(DREG) - (UINT64)(EXTRA_U); + CHECK_VSUB(EXTRA_U,DREG,tmp); + + if( DREG == EXTRA_U ) + SET_Z(1); + else + SET_Z(0); + + if( (INT32) DREG < (INT32) EXTRA_U ) + SET_N(1); + else + SET_N(0); + + if( DREG < EXTRA_U ) + SET_C(1); + else + SET_C(0); + + hyperstone_ICount -= 1; +} + +static void hyperstone_movi(void) +{ + if( !GET_S && current_regs.dst >= 16 ) + { + UINT32 addr = get_trap_addr(PRIVILEGE_ERROR); + execute_exception(addr); + } + + SET_DREG(EXTRA_U); + + if( DST_IS_PC ) + SET_M(0); + + SET_Z( EXTRA_U == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(EXTRA_U) ); + +#if MISSIONCRAFT_FLAGS + SET_V(0); // or V undefined ? +#endif + + hyperstone_ICount -= 1; +} + +static void hyperstone_addi(void) +{ + UINT32 imm; + UINT64 tmp; + + if( N_VALUE ) + imm = EXTRA_U; + else + imm = GET_C & ((GET_Z == 0 ? 1 : 0) | (DREG & 0x01)); + + + tmp = (UINT64)(imm) + (UINT64)(DREG); + CHECK_C(tmp); + CHECK_VADD(imm,DREG,tmp); + + DREG = imm + DREG; + SET_DREG(DREG); + + if( DST_IS_PC ) + SET_M(0); + + SET_Z( DREG == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(DREG) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_addsi(void) +{ + INT32 imm, res; + INT64 tmp; + + if( N_VALUE ) + imm = EXTRA_S; + else + imm = GET_C & ((GET_Z == 0 ? 1 : 0) | (DREG & 0x01)); + + tmp = (INT64)(imm) + (INT64)((INT32)(DREG)); + CHECK_VADD(imm,DREG,tmp); + +//#if SETCARRYS +// CHECK_C(tmp); +//#endif + + res = imm + (INT32)(DREG); + + SET_DREG(res); + + SET_Z( res == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(res) ); + + hyperstone_ICount -= 1; + + if( GET_V ) + { + UINT32 addr = get_trap_addr(RANGE_ERROR); + execute_exception(addr); + } +} + +static void hyperstone_cmpbi(void) +{ + UINT32 imm; + + if( N_VALUE ) + { + if( N_VALUE == 31 ) + { + imm = 0x7fffffff; // bit 31 = 0, others = 1 + } + else + { + imm = EXTRA_U; + } + + SET_Z( (DREG & imm) == 0 ? 1 : 0 ); + } + else + { + if( (DREG & 0xff000000) == 0 || (DREG & 0x00ff0000) == 0 || + (DREG & 0x0000ff00) == 0 || (DREG & 0x000000ff) == 0 ) + SET_Z(1); + else + SET_Z(0); + } + + hyperstone_ICount -= 1; +} + +static void hyperstone_andni(void) +{ + UINT32 imm; + + if( N_VALUE == 31 ) + imm = 0x7fffffff; // bit 31 = 0, others = 1 + else + imm = EXTRA_U; + + DREG = DREG & ~imm; + + SET_DREG(DREG); + SET_Z( DREG == 0 ? 1 : 0 ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_ori(void) +{ + DREG = DREG | EXTRA_U; + + SET_DREG(DREG); + SET_Z( DREG == 0 ? 1 : 0 ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_xori(void) +{ + DREG = DREG ^ EXTRA_U; + + SET_DREG(DREG); + SET_Z( DREG == 0 ? 1 : 0 ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_shrdi(void) +{ + UINT32 low_order, high_order; + UINT64 val; + + high_order = DREG; + low_order = DREGF; + + val = COMBINE_U64_U32_U32(high_order, low_order); + + if( N_VALUE ) + SET_C((val >> (N_VALUE - 1)) & 1); + else + SET_C(0); + + val >>= N_VALUE; + + high_order = HI32_32_64(val); + low_order = LO32_32_64(val); + + SET_DREG(high_order); + SET_DREGF(low_order); + SET_Z( val == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(high_order) ); + + hyperstone_ICount -= 2; +} + +static void hyperstone_shrd(void) +{ + UINT32 low_order, high_order; + UINT64 val; + UINT8 n = SREG & 0x1f; + + // result undefined if Ls denotes the same register as Ld or Ldf + if( SAME_SRC_DST || SAME_SRC_DSTF ) + { + logerror("Denoted same registers in hyperstone_shrd. PC = %08X\n", PC); + } + else + { + high_order = DREG; + low_order = DREGF; + + val = COMBINE_U64_U32_U32(high_order, low_order); + + if( n ) + SET_C((val >> (n - 1)) & 1); + else + SET_C(0); + + val >>= n; + + high_order = HI32_32_64(val); + low_order = LO32_32_64(val); + + SET_DREG(high_order); + SET_DREGF(low_order); + + SET_Z( val == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(high_order) ); + } + + hyperstone_ICount -= 2; +} + +static void hyperstone_shr(void) +{ + UINT32 ret; + UINT8 n; + + n = SREG & 0x1f; + ret = DREG; + + if( n ) + SET_C((ret >> (n - 1)) & 1); + else + SET_C(0); + + ret >>= n; + + SET_DREG(ret); + SET_Z( ret == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(ret) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_sardi(void) +{ + UINT32 low_order, high_order; + UINT64 val; + UINT8 sign_bit; + + high_order = DREG; + low_order = DREGF; + + val = COMBINE_64_32_32(high_order, low_order); + + if( N_VALUE ) + SET_C((val >> (N_VALUE - 1)) & 1); + else + SET_C(0); + + sign_bit = val >> 63; + val >>= N_VALUE; + + if( sign_bit ) + { + int i; + for( i = 0; i < N_VALUE; i++ ) + { + val |= (U64(0x8000000000000000) >> i); + } + } + + high_order = val >> 32; + low_order = val & 0xffffffff; + + SET_DREG(high_order); + SET_DREGF(low_order); + + SET_Z( val == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(high_order) ); + + hyperstone_ICount -= 2; +} + +static void hyperstone_sard(void) +{ + UINT32 low_order, high_order; + UINT64 val; + UINT8 n, sign_bit; + + n = SREG & 0x1f; + + // result undefined if Ls denotes the same register as Ld or Ldf + if( SAME_SRC_DST || SAME_SRC_DSTF ) + { + logerror("Denoted same registers in hyperstone_sard. PC = %08X\n", PC); + } + else + { + high_order = DREG; + low_order = DREGF; + + val = COMBINE_64_32_32(high_order, low_order); + + if( n ) + SET_C((val >> (n - 1)) & 1); + else + SET_C(0); + + sign_bit = val >> 63; + + val >>= n; + + if( sign_bit ) + { + int i; + for( i = 0; i < n; i++ ) + { + val |= (U64(0x8000000000000000) >> i); + } + } + + high_order = val >> 32; + low_order = val & 0xffffffff; + + SET_DREG(high_order); + SET_DREGF(low_order); + SET_Z( val == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(high_order) ); + } + + hyperstone_ICount -= 2; +} + +static void hyperstone_sar(void) +{ + UINT32 ret; + UINT8 n, sign_bit; + + n = SREG & 0x1f; + ret = DREG; + sign_bit = (ret & 0x80000000) >> 31; + + if( n ) + SET_C((ret >> (n - 1)) & 1); + else + SET_C(0); + + ret >>= n; + + if( sign_bit ) + { + int i; + for( i = 0; i < n; i++ ) + { + ret |= (0x80000000 >> i); + } + } + + SET_DREG(ret); + SET_Z( ret == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(ret) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_shldi(void) +{ + UINT32 low_order, high_order, tmp; + UINT64 val, mask; + + high_order = DREG; + low_order = DREGF; + + val = COMBINE_U64_U32_U32(high_order, low_order); + SET_C( (N_VALUE)?(((val<<(N_VALUE-1))&U64(0x8000000000000000))?1:0):0); + mask = ((((UINT64)1) << (32 - N_VALUE)) - 1) ^ 0xffffffff; + tmp = high_order << N_VALUE; + + if( ((high_order & mask) && (!(tmp & 0x80000000))) || + (((high_order & mask) ^ mask) && (tmp & 0x80000000)) ) + SET_V(1); + else + SET_V(0); + + val <<= N_VALUE; + + high_order = HI32_32_64(val); + low_order = LO32_32_64(val); + + SET_DREG(high_order); + SET_DREGF(low_order); + + SET_Z( val == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(high_order) ); + + hyperstone_ICount -= 2; +} + +static void hyperstone_shld(void) +{ + UINT32 low_order, high_order, tmp, n; + UINT64 val, mask; + + n = SREG & 0x1f; + + // result undefined if Ls denotes the same register as Ld or Ldf + if( SAME_SRC_DST || SAME_SRC_DSTF ) + { + logerror("Denoted same registers in hyperstone_shld. PC = %08X\n", PC); + } + else + { + high_order = DREG; + low_order = DREGF; + + mask = ((((UINT64)1) << (32 - n)) - 1) ^ 0xffffffff; + + val = COMBINE_U64_U32_U32(high_order, low_order); + SET_C( (n)?(((val<<(n-1))&U64(0x8000000000000000))?1:0):0); + tmp = high_order << n; + + if( ((high_order & mask) && (!(tmp & 0x80000000))) || + (((high_order & mask) ^ mask) && (tmp & 0x80000000)) ) + SET_V(1); + else + SET_V(0); + + val <<= n; + + high_order = HI32_32_64(val); + low_order = LO32_32_64(val); + + SET_DREG(high_order); + SET_DREGF(low_order); + + SET_Z( val == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(high_order) ); + } + + hyperstone_ICount -= 2; +} + +static void hyperstone_shl(void) +{ + UINT32 base, ret, n; + UINT64 mask; + + n = SREG & 0x1f; + base = DREG; + mask = ((((UINT64)1) << (32 - n)) - 1) ^ 0xffffffff; + SET_C( (n)?(((base<<(n-1))&0x80000000)?1:0):0); + ret = base << n; + + if( ((base & mask) && (!(ret & 0x80000000))) || + (((base & mask) ^ mask) && (ret & 0x80000000)) ) + SET_V(1); + else + SET_V(0); + + SET_DREG(ret); + SET_Z( ret == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(ret) ); + + hyperstone_ICount -= 1; +} + +static void reserved(void) +{ + logerror("Executed Reserved opcode. PC = %08X OP = %04X\n", PC, OP); +} + +static void hyperstone_testlz(void) +{ + UINT8 zeros = 0; + UINT32 mask; + + for( mask = 0x80000000; ; mask >>= 1 ) + { + if( SREG & mask ) + break; + else + zeros++; + + if( zeros == 32 ) + break; + } + + SET_DREG(zeros); + + hyperstone_ICount -= 2; +} + +static void hyperstone_rol(void) +{ + UINT32 val, base; + UINT8 n; + UINT64 mask; + + n = SREG & 0x1f; + + val = base = DREG; + + mask = ((((UINT64)1) << (32 - n)) - 1) ^ 0xffffffff; + + while( n > 0 ) + { + val = (val << 1) | ((val & 0x80000000) >> 31); + n--; + } + +#ifdef MISSIONCRAFT_FLAGS + + if( ((base & mask) && (!(val & 0x80000000))) || + (((base & mask) ^ mask) && (val & 0x80000000)) ) + SET_V(1); + else + SET_V(0); + +#endif + + SET_DREG(val); + + SET_Z( val == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(val) ); + + hyperstone_ICount -= 1; +} + +//TODO: add trap error +static void hyperstone_ldxx1(void) +{ + UINT32 load; + + if( DST_IS_SR ) + { + switch( current_regs.sub_type ) + { + case 0: // LDBS.A + + load = READ_B(EXTRA_S); + load |= (load & 0x80) ? 0xffffff00 : 0; + SET_SREG(load); + + break; + + case 1: // LDBU.A + + load = READ_B(EXTRA_S); + SET_SREG(load); + + break; + + case 2: + + load = READ_HW(EXTRA_S & ~1); + + if( EXTRA_S & 1 ) // LDHS.A + { + load |= (load & 0x8000) ? 0xffff0000 : 0; + } + /* + else // LDHU.A + { + // nothing more + } + */ + + SET_SREG(load); + + break; + + case 3: + + if( (EXTRA_S & 3) == 3 ) // LDD.IOA + { + load = IO_READ_W(EXTRA_S & ~3); + SET_SREG(load); + + load = IO_READ_W((EXTRA_S & ~3) + 4); + SET_SREGF(load); + + hyperstone_ICount -= 1; // extra cycle + } + else if( (EXTRA_S & 3) == 2 ) // LDW.IOA + { + load = IO_READ_W(EXTRA_S & ~3); + SET_SREG(load); + } + else if( (EXTRA_S & 3) == 1 ) // LDD.A + { + load = READ_W(EXTRA_S & ~1); + SET_SREG(load); + + load = READ_W((EXTRA_S & ~1) + 4); + SET_SREGF(load); + + hyperstone_ICount -= 1; // extra cycle + } + else // LDW.A + { + load = READ_W(EXTRA_S & ~1); + SET_SREG(load); + } + + break; + } + } + else + { + switch( current_regs.sub_type ) + { + case 0: // LDBS.D + + load = READ_B(DREG + EXTRA_S); + load |= (load & 0x80) ? 0xffffff00 : 0; + SET_SREG(load); + + break; + + case 1: // LDBU.D + + load = READ_B(DREG + EXTRA_S); + SET_SREG(load); + + break; + + case 2: + + load = READ_HW(DREG + (EXTRA_S & ~1)); + + if( EXTRA_S & 1 ) // LDHS.D + { + load |= (load & 0x8000) ? 0xffff0000 : 0; + } + /* + else // LDHU.D + { + // nothing more + } + */ + + SET_SREG(load); + + break; + + case 3: + + if( (EXTRA_S & 3) == 3 ) // LDD.IOD + { + load = IO_READ_W(DREG + (EXTRA_S & ~3)); + SET_SREG(load); + + load = IO_READ_W(DREG + (EXTRA_S & ~3) + 4); + SET_SREGF(load); + + hyperstone_ICount -= 1; // extra cycle + } + else if( (EXTRA_S & 3) == 2 ) // LDW.IOD + { + load = IO_READ_W(DREG + (EXTRA_S & ~3)); + SET_SREG(load); + } + else if( (EXTRA_S & 3) == 1 ) // LDD.D + { + load = READ_W(DREG + (EXTRA_S & ~1)); + SET_SREG(load); + + load = READ_W(DREG + (EXTRA_S & ~1) + 4); + SET_SREGF(load); + + hyperstone_ICount -= 1; // extra cycle + } + else // LDW.D + { + load = READ_W(DREG + (EXTRA_S & ~1)); + SET_SREG(load); + } + + break; + } + } + + hyperstone_ICount -= 1; +} + +static void hyperstone_ldxx2(void) +{ + UINT32 load; + + if( DST_IS_PC || DST_IS_SR ) + { + logerror("Denoted PC or SR in hyperstone_ldxx2. PC = %08X\n", PC); + } + else + { + switch( current_regs.sub_type ) + { + case 0: // LDBS.N + + if(SAME_SRC_DST) + popmessage("LDBS.N denoted same regs @ %08X",PPC); + + load = READ_B(DREG); + load |= (load & 0x80) ? 0xffffff00 : 0; + SET_SREG(load); + + if(!SAME_SRC_DST) + SET_DREG(DREG + EXTRA_S); + + break; + + case 1: // LDBU.N + + if(SAME_SRC_DST) + popmessage("LDBU.N denoted same regs @ %08X",PPC); + + load = READ_B(DREG); + SET_SREG(load); + + if(!SAME_SRC_DST) + SET_DREG(DREG + EXTRA_S); + + break; + + case 2: + + load = READ_HW(DREG); + + if( EXTRA_S & 1 ) // LDHS.N + { + load |= (load & 0x8000) ? 0xffff0000 : 0; + + if(SAME_SRC_DST) + popmessage("LDHS.N denoted same regs @ %08X",PPC); + } + /* + else // LDHU.N + { + // nothing more + } + */ + + SET_SREG(load); + + if(!SAME_SRC_DST) + SET_DREG(DREG + (EXTRA_S & ~1)); + + break; + + case 3: + + if( (EXTRA_S & 3) == 3 ) // LDW.S + { + if(SAME_SRC_DST) + popmessage("LDW.S denoted same regs @ %08X",PPC); + + if(DREG < SP) + SET_SREG(READ_W(DREG)); + else + SET_SREG(GET_ABS_L_REG((DREG & 0xfc) >> 2)); + + if(!SAME_SRC_DST) + SET_DREG(DREG + (EXTRA_S & ~3)); + + hyperstone_ICount -= 2; // extra cycles + } + else if( (EXTRA_S & 3) == 2 ) // Reserved + { + logerror("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC); + } + else if( (EXTRA_S & 3) == 1 ) // LDD.N + { + if(SAME_SRC_DST || SAME_SRCF_DST) + popmessage("LDD.N denoted same regs @ %08X",PPC); + + load = READ_W(DREG); + SET_SREG(load); + + load = READ_W(DREG + 4); + SET_SREGF(load); + + if(!SAME_SRC_DST && !SAME_SRCF_DST) + SET_DREG(DREG + (EXTRA_S & ~1)); + + hyperstone_ICount -= 1; // extra cycle + } + else // LDW.N + { + if(SAME_SRC_DST) + popmessage("LDW.N denoted same regs @ %08X",PPC); + + load = READ_W(DREG); + SET_SREG(load); + + if(!SAME_SRC_DST) + SET_DREG(DREG + (EXTRA_S & ~1)); + } + + break; + } + } + + hyperstone_ICount -= 1; +} + +//TODO: add trap error +static void hyperstone_stxx1(void) +{ + if( SRC_IS_SR ) + SREG = SREGF = 0; + + if( DST_IS_SR ) + { + switch( current_regs.sub_type ) + { + case 0: // STBS.A + + /* TODO: missing trap on range error */ + WRITE_B(EXTRA_S, SREG & 0xff); + + break; + + case 1: // STBU.A + + WRITE_B(EXTRA_S, SREG & 0xff); + + break; + + case 2: + + WRITE_HW(EXTRA_S & ~1, SREG & 0xffff); + + /* + if( EXTRA_S & 1 ) // STHS.A + { + // TODO: missing trap on range error + } + else // STHU.A + { + // nothing more + } + */ + + break; + + case 3: + + if( (EXTRA_S & 3) == 3 ) // STD.IOA + { + IO_WRITE_W(EXTRA_S & ~3, SREG); + IO_WRITE_W((EXTRA_S & ~3) + 4, SREGF); + + hyperstone_ICount -= 1; // extra cycle + } + else if( (EXTRA_S & 3) == 2 ) // STW.IOA + { + IO_WRITE_W(EXTRA_S & ~3, SREG); + } + else if( (EXTRA_S & 3) == 1 ) // STD.A + { + WRITE_W(EXTRA_S & ~1, SREG); + WRITE_W((EXTRA_S & ~1) + 4, SREGF); + + hyperstone_ICount -= 1; // extra cycle + } + else // STW.A + { + WRITE_W(EXTRA_S & ~1, SREG); + } + + break; + } + } + else + { + switch( current_regs.sub_type ) + { + case 0: // STBS.D + + /* TODO: missing trap on range error */ + WRITE_B(DREG + EXTRA_S, SREG & 0xff); + + break; + + case 1: // STBU.D + + WRITE_B(DREG + EXTRA_S, SREG & 0xff); + + break; + + case 2: + + WRITE_HW(DREG + (EXTRA_S & ~1), SREG & 0xffff); + + /* + if( EXTRA_S & 1 ) // STHS.D + { + // TODO: missing trap on range error + } + else // STHU.D + { + // nothing more + } + */ + + break; + + case 3: + + if( (EXTRA_S & 3) == 3 ) // STD.IOD + { + IO_WRITE_W(DREG + (EXTRA_S & ~3), SREG); + IO_WRITE_W(DREG + (EXTRA_S & ~3) + 4, SREGF); + + hyperstone_ICount -= 1; // extra cycle + } + else if( (EXTRA_S & 3) == 2 ) // STW.IOD + { + IO_WRITE_W(DREG + (EXTRA_S & ~3), SREG); + } + else if( (EXTRA_S & 3) == 1 ) // STD.D + { + WRITE_W(DREG + (EXTRA_S & ~1), SREG); + WRITE_W(DREG + (EXTRA_S & ~1) + 4, SREGF); + + hyperstone_ICount -= 1; // extra cycle + } + else // STW.D + { + WRITE_W(DREG + (EXTRA_S & ~1), SREG); + } + + break; + } + } + + hyperstone_ICount -= 1; +} + +static void hyperstone_stxx2(void) +{ + if( SRC_IS_SR ) + SREG = SREGF = 0; + + if( DST_IS_PC || DST_IS_SR ) + { + logerror("Denoted PC or SR in hyperstone_stxx2. PC = %08X\n", PC); + } + else + { + switch( current_regs.sub_type ) + { + case 0: // STBS.N + + /* TODO: missing trap on range error */ + WRITE_B(DREG, SREG & 0xff); + SET_DREG(DREG + EXTRA_S); + + break; + + case 1: // STBU.N + + WRITE_B(DREG, SREG & 0xff); + SET_DREG(DREG + EXTRA_S); + + break; + + case 2: + + WRITE_HW(DREG, SREG & 0xffff); + SET_DREG(DREG + (EXTRA_S & ~1)); + + /* + if( EXTRA_S & 1 ) // STHS.N + { + // TODO: missing trap on range error + } + else // STHU.N + { + // nothing more + } + */ + + break; + + case 3: + + if( (EXTRA_S & 3) == 3 ) // STW.S + { + if(DREG < SP) + WRITE_W(DREG, SREG); + else + { + if(((DREG & 0xfc) >> 2) == ((current_regs.src + GET_FP) % 64) && S_BIT == LOCAL) + popmessage("STW.S denoted the same local register @ %08X\n",PPC); + + SET_ABS_L_REG((DREG & 0xfc) >> 2,SREG); + } + + SET_DREG(DREG + (EXTRA_S & ~3)); + + hyperstone_ICount -= 2; // extra cycles + + } + else if( (EXTRA_S & 3) == 2 ) // Reserved + { + logerror("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC); + } + else if( (EXTRA_S & 3) == 1 ) // STD.N + { + WRITE_W(DREG, SREG); + SET_DREG(DREG + (EXTRA_S & ~1)); + + if( SAME_SRCF_DST ) + WRITE_W(DREG + 4, SREGF + (EXTRA_S & ~1)); // because DREG == SREGF and DREG has been incremented + else + WRITE_W(DREG + 4, SREGF); + + hyperstone_ICount -= 1; // extra cycle + } + else // STW.N + { + WRITE_W(DREG, SREG); + SET_DREG(DREG + (EXTRA_S & ~1)); + } + + break; + } + } + + hyperstone_ICount -= 1; +} + +static void hyperstone_shri(void) +{ + UINT32 val; + + val = DREG; + + if( N_VALUE ) + SET_C((val >> (N_VALUE - 1)) & 1); + else + SET_C(0); + + val >>= N_VALUE; + + SET_DREG(val); + SET_Z( val == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(val) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_sari(void) +{ + UINT32 val; + UINT8 sign_bit; + + val = DREG; + sign_bit = (val & 0x80000000) >> 31; + + if( N_VALUE ) + SET_C((val >> (N_VALUE - 1)) & 1); + else + SET_C(0); + + val >>= N_VALUE; + + if( sign_bit ) + { + int i; + for( i = 0; i < N_VALUE; i++ ) + { + val |= (0x80000000 >> i); + } + } + + SET_DREG(val); + SET_Z( val == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(val) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_shli(void) +{ + UINT32 val, val2; + UINT64 mask; + + val = DREG; + SET_C( (N_VALUE)?(((val<<(N_VALUE-1))&0x80000000)?1:0):0); + mask = ((((UINT64)1) << (32 - N_VALUE)) - 1) ^ 0xffffffff; + val2 = val << N_VALUE; + + if( ((val & mask) && (!(val2 & 0x80000000))) || + (((val & mask) ^ mask) && (val2 & 0x80000000)) ) + SET_V(1); + else + SET_V(0); + + SET_DREG(val2); + SET_Z( val2 == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(val2) ); + + hyperstone_ICount -= 1; +} + +static void hyperstone_mulu(void) +{ + UINT32 low_order, high_order; + UINT64 double_word; + + // PC or SR aren't denoted, else result is undefined + if( SRC_IS_PC || SRC_IS_SR || DST_IS_PC || DST_IS_SR ) + { + logerror("Denoted PC or SR in hyperstone_mulu instruction. PC = %08X\n", PC); + } + else + { + double_word = (UINT64)SREG *(UINT64)DREG; + + low_order = double_word & 0xffffffff; + high_order = double_word >> 32; + + SET_DREG(high_order); + SET_DREGF(low_order); + + SET_Z( double_word == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(high_order) ); + } + + if(SREG <= 0xffff && DREG <= 0xffff) + hyperstone_ICount -= 4; + else + hyperstone_ICount -= 6; +} + +static void hyperstone_muls(void) +{ + UINT32 low_order, high_order; + INT64 double_word; + + // PC or SR aren't denoted, else result is undefined + if( SRC_IS_PC || SRC_IS_SR || DST_IS_PC || DST_IS_SR ) + { + logerror("Denoted PC or SR in hyperstone_muls instruction. PC = %08X\n", PC); + } + else + { + double_word = (INT64)(INT32)(SREG) * (INT64)(INT32)(DREG); + low_order = double_word & 0xffffffff; + high_order = double_word >> 32; + + SET_DREG(high_order); + SET_DREGF(low_order); + + SET_Z( double_word == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(high_order) ); + } + + if((SREG >= 0xffff8000 && SREG <= 0x7fff) && (DREG >= 0xffff8000 && DREG <= 0x7fff)) + hyperstone_ICount -= 4; + else + hyperstone_ICount -= 6; +} + +static void hyperstone_set(void) +{ + int n = N_VALUE; + + if( DST_IS_PC ) + { + logerror("Denoted PC in hyperstone_set. PC = %08X\n", PC); + } + else if( DST_IS_SR ) + { + //TODO: add fetch opcode when there's the pipeline + + //TODO: no 1! + hyperstone_ICount -= 1; + } + else + { + switch( n ) + { + // SETADR + case 0: + { + UINT32 val; + val = (SP & 0xfffffe00) | (GET_FP << 2); + + //plus carry into bit 9 + val += (( (SP & 0x100) && (SIGN_BIT(SR) == 0) ) ? 1 : 0); + + SET_DREG(val); + + break; + } + // Reserved + case 1: + case 16: + case 17: + case 19: + logerror("Used reserved N value (%d) in hyperstone_set. PC = %08X\n", n, PC); + break; + + // SETxx + case 2: + SET_DREG(1); + break; + + case 3: + SET_DREG(0); + break; + + case 4: + if( GET_N || GET_Z ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 5: + if( !GET_N && !GET_Z ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 6: + if( GET_N ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 7: + if( !GET_N ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 8: + if( GET_C || GET_Z ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 9: + if( !GET_C && !GET_Z ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 10: + if( GET_C ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 11: + if( !GET_C ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 12: + if( GET_Z ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 13: + if( !GET_Z ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 14: + if( GET_V ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 15: + if( !GET_V ) + { + SET_DREG(1); + } + else + { + SET_DREG(0); + } + + break; + + case 18: + SET_DREG(-1); + break; + + case 20: + if( GET_N || GET_Z ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 21: + if( !GET_N && !GET_Z ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 22: + if( GET_N ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 23: + if( !GET_N ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 24: + if( GET_C || GET_Z ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 25: + if( !GET_C && !GET_Z ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 26: + if( GET_C ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 27: + if( !GET_C ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 28: + if( GET_Z ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 29: + if( !GET_Z ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 30: + if( GET_V ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + + case 31: + if( !GET_V ) + { + SET_DREG(-1); + } + else + { + SET_DREG(0); + } + + break; + } + + hyperstone_ICount -= 1; + } +} + +static void hyperstone_mul(void) +{ + UINT32 single_word; + + // PC or SR aren't denoted, else result is undefined + if( SRC_IS_PC || SRC_IS_SR || DST_IS_PC || DST_IS_SR ) + { + logerror("Denoted PC or SR in hyperstone_mul instruction. PC = %08X\n", PC); + } + else + { + single_word = (SREG * DREG);// & 0xffffffff; // only the low-order word is taken + + SET_DREG(single_word); + + SET_Z( single_word == 0 ? 1 : 0 ); + SET_N( SIGN_BIT(single_word) ); + } + + if((SREG >= 0xffff8000 && SREG <= 0x7fff) && (DREG >= 0xffff8000 && DREG <= 0x7fff)) + hyperstone_ICount -= 3; + else + hyperstone_ICount -= 5; +} + +static void hyperstone_fadd(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_faddd(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fsub(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fsubd(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fmul(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fmuld(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fdiv(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fdivd(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fcmp(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fcmpd(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fcmpu(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fcmpud(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fcvt(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_fcvtd(void) +{ + execute_software(); + hyperstone_ICount -= 6; +} + +static void hyperstone_extend(void) +{ + //TODO: add locks, overflow error and other things + UINT32 vals, vald; + + vals = SREG; + vald = DREG; + + switch( EXTRA_U ) // extended opcode + { + // signed or unsigned multiplication, single word product + case EMUL: + case 0x100: // used in "N" type cpu + { + UINT32 result; + + result = vals * vald; + SET_G_REG(15, result); + + break; + } + // unsigned multiplication, double word product + case EMULU: + { + UINT64 result; + + result = (UINT64)vals * (UINT64)vald; + vals = result >> 32; + vald = result & 0xffffffff; + SET_G_REG(14, vals); + SET_G_REG(15, vald); + + break; + } + // signed multiplication, double word product + case EMULS: + { + INT64 result; + + result = (INT64)(INT32)(vals) * (INT64)(INT32)(vald); + vals = result >> 32; + vald = result & 0xffffffff; + SET_G_REG(14, vals); + SET_G_REG(15, vald); + + break; + } + // signed multiply/add, single word product sum + case EMAC: + { + INT32 result; + + result = (INT32)GET_G_REG(15) + ((INT32)(vals) * (INT32)(vald)); + SET_G_REG(15, result); + + break; + } + // signed multiply/add, double word product sum + case EMACD: + { + INT64 result; + + result = (INT64)COMBINE_64_32_32(GET_G_REG(14), GET_G_REG(15)) + (INT64)((INT64)(INT32)(vals) * (INT64)(INT32)(vald)); + + vals = result >> 32; + vald = result & 0xffffffff; + SET_G_REG(14, vals); + SET_G_REG(15, vald); + + break; + } + // signed multiply/substract, single word product difference + case EMSUB: + { + INT32 result; + + result = (INT32)GET_G_REG(15) - ((INT32)(vals) * (INT32)(vald)); + SET_G_REG(15, result); + + break; + } + // signed multiply/substract, double word product difference + case EMSUBD: + { + INT64 result; + + result = (INT64)COMBINE_64_32_32(GET_G_REG(14), GET_G_REG(15)) - (INT64)((INT64)(INT32)(vals) * (INT64)(INT32)(vald)); + + vals = result >> 32; + vald = result & 0xffffffff; + SET_G_REG(14, vals); + SET_G_REG(15, vald); + + break; + } + // signed half-word multiply/add, single word product sum + case EHMAC: + { + INT32 result; + + result = (INT32)GET_G_REG(15) + ((INT32)((vald & 0xffff0000) >> 16) * (INT32)((vals & 0xffff0000) >> 16)) + ((INT32)(vald & 0xffff) * (INT32)(vals & 0xffff)); + SET_G_REG(15, result); + + break; + } + // signed half-word multiply/add, double word product sum + case EHMACD: + { + INT64 result; + + result = (INT64)COMBINE_64_32_32(GET_G_REG(14), GET_G_REG(15)) + (INT64)((INT64)(INT32)((vald & 0xffff0000) >> 16) * (INT64)(INT32)((vals & 0xffff0000) >> 16)) + ((INT64)(INT32)(vald & 0xffff) * (INT64)(INT32)(vals & 0xffff)); + + vals = result >> 32; + vald = result & 0xffffffff; + SET_G_REG(14, vals); + SET_G_REG(15, vald); + + break; + } + // half-word complex multiply + case EHCMULD: + { + UINT32 result; + + result = (((vald & 0xffff0000) >> 16) * ((vals & 0xffff0000) >> 16)) - ((vald & 0xffff) * (vals & 0xffff)); + SET_G_REG(14, result); + + result = (((vald & 0xffff0000) >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * ((vals & 0xffff0000) >> 16)); + SET_G_REG(15, result); + + break; + } + // half-word complex multiply/add + case EHCMACD: + { + UINT32 result; + + result = GET_G_REG(14) + (((vald & 0xffff0000) >> 16) * ((vals & 0xffff0000) >> 16)) - ((vald & 0xffff) * (vals & 0xffff)); + SET_G_REG(14, result); + + result = GET_G_REG(15) + (((vald & 0xffff0000) >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * ((vals & 0xffff0000) >> 16)); + SET_G_REG(15, result); + + break; + } + // half-word (complex) add/substract + // Ls is not used and should denote the same register as Ld + case EHCSUMD: + { + UINT32 result; + + result = ((((vals & 0xffff0000) >> 16) + GET_G_REG(14)) << 16) & 0xffff0000; + result |= ((vals & 0xffff) + GET_G_REG(15)) & 0xffff; + SET_G_REG(14, result); + + result = ((((vals & 0xffff0000) >> 16) - GET_G_REG(14)) << 16) & 0xffff0000; + result |= ((vals & 0xffff) - GET_G_REG(15)) & 0xffff; + SET_G_REG(15, result); + + break; + } + // half-word (complex) add/substract with fixed point adjustment + // Ls is not used and should denote the same register as Ld + case EHCFFTD: + { + UINT32 result; + + result = ((((vals & 0xffff0000) >> 16) + (GET_G_REG(14) >> 15)) << 16) & 0xffff0000; + result |= ((vals & 0xffff) + (GET_G_REG(15) >> 15)) & 0xffff; + SET_G_REG(14, result); + + result = ((((vals & 0xffff0000) >> 16) - (GET_G_REG(14) >> 15)) << 16) & 0xffff0000; + result |= ((vals & 0xffff) - (GET_G_REG(15) >> 15)) & 0xffff; + SET_G_REG(15, result); + + break; + } + // half-word (complex) add/substract with fixed point adjustment and shift + // Ls is not used and should denote the same register as Ld + case EHCFFTSD: + { + UINT32 result; + + result = (((((vals & 0xffff0000) >> 16) + (GET_G_REG(14) >> 15)) >> 1) << 16) & 0xffff0000; + result |= ((((vals & 0xffff) + (GET_G_REG(15) >> 15)) >> 1) & 0xffff); + SET_G_REG(14, result); + + result = (((((vals & 0xffff0000) >> 16) - (GET_G_REG(14) >> 15)) >> 1) << 16) & 0xffff0000; + result |= ((((vals & 0xffff) - (GET_G_REG(15) >> 15)) >> 1) & 0xffff); + SET_G_REG(15, result); + + break; + } + default: + logerror("Executed Illegal extended opcode (%X). PC = %08X\n", EXTRA_U, PC); + break; + } + + hyperstone_ICount -= 1; //TODO: with the latency it can change +} + +static void hyperstone_do(void) +{ + fatalerror("Executed hyperstone_do instruction. PC = %08X", PPC); +} + +static void hyperstone_ldwr(void) +{ + SET_SREG(READ_W(DREG)); + + hyperstone_ICount -= 1; +} + +static void hyperstone_lddr(void) +{ + SET_SREG(READ_W(DREG)); + SET_SREGF(READ_W(DREG + 4)); + + hyperstone_ICount -= 2; +} + +static void hyperstone_ldwp(void) +{ + SET_SREG(READ_W(DREG)); + + // post increment the destination register if it's different from the source one + // (needed by Hidden Catch) + if(!(current_regs.src == current_regs.dst && S_BIT == LOCAL)) + SET_DREG(DREG + 4); + + hyperstone_ICount -= 1; +} + +static void hyperstone_lddp(void) +{ + SET_SREG(READ_W(DREG)); + SET_SREGF(READ_W(DREG + 4)); + + // post increment the destination register if it's different from the source one + // and from the "next source" one + if(!(current_regs.src == current_regs.dst && S_BIT == LOCAL) && !SAME_SRCF_DST ) + { + SET_DREG(DREG + 8); + } + else + { + popmessage("LDD.P denoted same regs @ %08X",PPC); + } + + hyperstone_ICount -= 2; +} + +static void hyperstone_stwr(void) +{ + if( SRC_IS_SR ) + SREG = 0; + + WRITE_W(DREG, SREG); + + hyperstone_ICount -= 1; +} + +static void hyperstone_stdr(void) +{ + if( SRC_IS_SR ) + SREG = SREGF = 0; + + WRITE_W(DREG, SREG); + WRITE_W(DREG + 4, SREGF); + + hyperstone_ICount -= 2; +} + +static void hyperstone_stwp(void) +{ + if( SRC_IS_SR ) + SREG = 0; + + WRITE_W(DREG, SREG); + SET_DREG(DREG + 4); + + hyperstone_ICount -= 1; +} + +static void hyperstone_stdp(void) +{ + if( SRC_IS_SR ) + SREG = SREGF = 0; + + WRITE_W(DREG, SREG); + SET_DREG(DREG + 8); + + if( SAME_SRCF_DST ) + WRITE_W(DREG + 4, SREGF + 8); // because DREG == SREGF and DREG has been incremented + else + WRITE_W(DREG + 4, SREGF); + + hyperstone_ICount -= 2; +} + +static void hyperstone_dbv(void) +{ + if( GET_V ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbnv(void) +{ + if( !GET_V ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbe(void) //or DBZ +{ + if( GET_Z ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbne(void) //or DBNZ +{ + if( !GET_Z ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbc(void) //or DBST +{ + if( GET_C ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbnc(void) //or DBHE +{ + if( !GET_C ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbse(void) +{ + if( GET_C || GET_Z ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbht(void) +{ + if( !GET_C && !GET_Z ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbn(void) //or DBLT +{ + if( GET_N ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbnn(void) //or DBGE +{ + if( !GET_N ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dble(void) +{ + if( GET_N || GET_Z ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbgt(void) +{ + if( !GET_N && !GET_Z ) + execute_dbr(); + + hyperstone_ICount -= 1; +} + +static void hyperstone_dbr(void) +{ + execute_dbr(); +} + +static void hyperstone_frame(void) +{ + INT8 difference; // really it's 7 bits + UINT8 realfp = GET_FP - SRC_CODE; + + SET_FP(realfp); + SET_FL(DST_CODE); + SET_M(0); + + difference = ((SP & 0x1fc) >> 2) + (64 - 10) - (realfp + GET_FL); + + /* convert to 8 bits */ + if(difference > 63) + difference = (INT8)(difference|0x80); + else if( difference < -64 ) + difference = difference & 0x7f; + + if( difference < 0 ) // else it's finished + { + UINT8 tmp_flag; + + tmp_flag = ( SP >= UB ? 1 : 0 ); + + do + { + WRITE_W(SP, GET_ABS_L_REG((SP & 0xfc) >> 2)); + SP += 4; + difference++; + + } while(difference != 0); + + if( tmp_flag ) + { + UINT32 addr = get_trap_addr(FRAME_ERROR); + execute_exception(addr); + } + } + + //TODO: no 1! + hyperstone_ICount -= 1; +} + +static void hyperstone_call(void) +{ + if( SRC_IS_SR ) + SREG = 0; + + if( !DST_CODE ) + current_regs.dst = 16; + + EXTRA_S = (EXTRA_S & ~1) + SREG; + + SET_ILC(hyperstone.instruction_length & 3); + + SET_DREG((PC & 0xfffffffe) | GET_S); + SET_DREGF(SR); + + SET_FP(GET_FP + current_regs.dst); + + SET_FL(6); //default value for call + SET_M(0); + + PPC = PC; + PC = EXTRA_S; // const value + change_pc(PC); + + hyperstone.intblock = 2; + + //TODO: add interrupt locks, errors, .... + + //TODO: no 1! + hyperstone_ICount -= 1; +} + +static void hyperstone_bv(void) +{ + if( GET_V ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_bnv(void) +{ + if( !GET_V ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_be(void) //or BZ +{ + if( GET_Z ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_bne(void) //or BNZ +{ + if( !GET_Z ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_bc(void) //or BST +{ + if( GET_C ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_bnc(void) //or BHE +{ + if( !GET_C ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_bse(void) +{ + if( GET_C || GET_Z ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_bht(void) +{ + if( !GET_C && !GET_Z ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_bn(void) //or BLT +{ + if( GET_N ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_bnn(void) //or BGE +{ + if( !GET_N ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_ble(void) +{ + if( GET_N || GET_Z ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_bgt(void) +{ + if( !GET_N && !GET_Z ) + execute_br(); + else + hyperstone_ICount -= 1; +} + +static void hyperstone_br(void) +{ + execute_br(); +} + +static void hyperstone_trap(void) +{ + UINT8 code, trapno; + UINT32 addr; + + trapno = (OP & 0xfc) >> 2; + + addr = get_trap_addr(trapno); + code = ((OP & 0x300) >> 6) | (OP & 0x03); + + switch( code ) + { + case TRAPLE: + if( GET_N || GET_Z ) + execute_trap(addr); + + break; + + case TRAPGT: + if( !GET_N && !GET_Z ) + execute_trap(addr); + + break; + + case TRAPLT: + if( GET_N ) + execute_trap(addr); + + break; + + case TRAPGE: + if( !GET_N ) + execute_trap(addr); + + break; + + case TRAPSE: + if( GET_C || GET_Z ) + execute_trap(addr); + + break; + + case TRAPHT: + if( !GET_C && !GET_Z ) + execute_trap(addr); + + break; + + case TRAPST: + if( GET_C ) + execute_trap(addr); + + break; + + case TRAPHE: + if( !GET_C ) + execute_trap(addr); + + break; + + case TRAPE: + if( GET_Z ) + execute_trap(addr); + + break; + + case TRAPNE: + if( !GET_Z ) + execute_trap(addr); + + break; + + case TRAPV: + if( GET_V ) + execute_trap(addr); + + break; + + case TRAP: + execute_trap(addr); + + break; + } + + hyperstone_ICount -= 1; +} + + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static void hyperstone_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + E132XS_PC: PC = info->i; change_pc(PC); break; + case CPUINFO_INT_REGISTER + E132XS_SR: SR = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_FER: FER = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G3: hyperstone.global_regs[3] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G4: hyperstone.global_regs[4] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G5: hyperstone.global_regs[5] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G6: hyperstone.global_regs[6] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G7: hyperstone.global_regs[7] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G8: hyperstone.global_regs[8] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G9: hyperstone.global_regs[9] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G10: hyperstone.global_regs[10] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G11: hyperstone.global_regs[11] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G12: hyperstone.global_regs[12] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G13: hyperstone.global_regs[13] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G14: hyperstone.global_regs[14] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G15: hyperstone.global_regs[15] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G16: hyperstone.global_regs[16] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G17: hyperstone.global_regs[17] = info->i; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + E132XS_SP: SP = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_UB: UB = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_BCR: BCR = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_TPR: TPR = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_TCR: TCR = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_TR: TR = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_WCR: WCR = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_ISR: ISR = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_FCR: FCR = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_MCR: MCR = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G28: hyperstone.global_regs[28] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G29: hyperstone.global_regs[29] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G30: hyperstone.global_regs[30] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_G31: hyperstone.global_regs[31] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL0: hyperstone.local_regs[(0 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL1: hyperstone.local_regs[(1 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL2: hyperstone.local_regs[(2 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL3: hyperstone.local_regs[(3 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL4: hyperstone.local_regs[(4 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL5: hyperstone.local_regs[(5 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL6: hyperstone.local_regs[(6 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL7: hyperstone.local_regs[(7 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL8: hyperstone.local_regs[(8 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL9: hyperstone.local_regs[(9 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL10: hyperstone.local_regs[(10 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL11: hyperstone.local_regs[(11 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL12: hyperstone.local_regs[(12 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL13: hyperstone.local_regs[(13 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL14: hyperstone.local_regs[(14 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_CL15: hyperstone.local_regs[(15 + GET_FP) % 64] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L0: hyperstone.local_regs[0] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L1: hyperstone.local_regs[1] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L2: hyperstone.local_regs[2] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L3: hyperstone.local_regs[3] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L4: hyperstone.local_regs[4] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L5: hyperstone.local_regs[5] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L6: hyperstone.local_regs[6] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L7: hyperstone.local_regs[7] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L8: hyperstone.local_regs[8] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L9: hyperstone.local_regs[9] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L10: hyperstone.local_regs[10] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L11: hyperstone.local_regs[11] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L12: hyperstone.local_regs[12] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L13: hyperstone.local_regs[13] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L14: hyperstone.local_regs[14] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L15: hyperstone.local_regs[15] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L16: hyperstone.local_regs[16] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L17: hyperstone.local_regs[17] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L18: hyperstone.local_regs[18] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L19: hyperstone.local_regs[19] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L20: hyperstone.local_regs[20] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L21: hyperstone.local_regs[21] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L22: hyperstone.local_regs[22] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L23: hyperstone.local_regs[23] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L24: hyperstone.local_regs[24] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L25: hyperstone.local_regs[25] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L26: hyperstone.local_regs[26] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L27: hyperstone.local_regs[27] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L28: hyperstone.local_regs[28] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L29: hyperstone.local_regs[29] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L30: hyperstone.local_regs[30] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L31: hyperstone.local_regs[31] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L32: hyperstone.local_regs[32] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L33: hyperstone.local_regs[33] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L34: hyperstone.local_regs[34] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L35: hyperstone.local_regs[35] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L36: hyperstone.local_regs[36] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L37: hyperstone.local_regs[37] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L38: hyperstone.local_regs[38] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L39: hyperstone.local_regs[39] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L40: hyperstone.local_regs[40] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L41: hyperstone.local_regs[41] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L42: hyperstone.local_regs[42] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L43: hyperstone.local_regs[43] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L44: hyperstone.local_regs[44] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L45: hyperstone.local_regs[45] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L46: hyperstone.local_regs[46] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L47: hyperstone.local_regs[47] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L48: hyperstone.local_regs[48] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L49: hyperstone.local_regs[49] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L50: hyperstone.local_regs[50] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L51: hyperstone.local_regs[51] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L52: hyperstone.local_regs[52] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L53: hyperstone.local_regs[53] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L54: hyperstone.local_regs[54] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L55: hyperstone.local_regs[55] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L56: hyperstone.local_regs[56] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L57: hyperstone.local_regs[57] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L58: hyperstone.local_regs[58] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L59: hyperstone.local_regs[59] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L60: hyperstone.local_regs[60] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L61: hyperstone.local_regs[61] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L62: hyperstone.local_regs[62] = info->i; break; + case CPUINFO_INT_REGISTER + E132XS_L63: hyperstone.local_regs[63] = info->i; break; + + case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(0, info->i); break; + case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(1, info->i); break; + case CPUINFO_INT_INPUT_STATE + 2: set_irq_line(2, info->i); break; + case CPUINFO_INT_INPUT_STATE + 3: set_irq_line(3, info->i); break; + case CPUINFO_INT_INPUT_STATE + 4: set_irq_line(4, info->i); break; + case CPUINFO_INT_INPUT_STATE + 5: set_irq_line(5, info->i); break; + case CPUINFO_INT_INPUT_STATE + 6: set_irq_line(6, info->i); break; + case CPUINFO_INT_INPUT_STATE + 7: set_irq_line(7, info->i); break; + } +} + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +void hyperstone_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(hyperstone_regs); break; + case CPUINFO_INT_INPUT_LINES: info->i = 8; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 6; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 36; break; + + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 15; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + 0: /* not implemented */ break; + + case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + E132XS_PC: info->i = PC; break; + case CPUINFO_INT_REGISTER + E132XS_SR: info->i = SR; break; + case CPUINFO_INT_REGISTER + E132XS_FER: info->i = FER; break; + case CPUINFO_INT_REGISTER + E132XS_G3: info->i = hyperstone.global_regs[3]; break; + case CPUINFO_INT_REGISTER + E132XS_G4: info->i = hyperstone.global_regs[4]; break; + case CPUINFO_INT_REGISTER + E132XS_G5: info->i = hyperstone.global_regs[5]; break; + case CPUINFO_INT_REGISTER + E132XS_G6: info->i = hyperstone.global_regs[6]; break; + case CPUINFO_INT_REGISTER + E132XS_G7: info->i = hyperstone.global_regs[7]; break; + case CPUINFO_INT_REGISTER + E132XS_G8: info->i = hyperstone.global_regs[8]; break; + case CPUINFO_INT_REGISTER + E132XS_G9: info->i = hyperstone.global_regs[9]; break; + case CPUINFO_INT_REGISTER + E132XS_G10: info->i = hyperstone.global_regs[10]; break; + case CPUINFO_INT_REGISTER + E132XS_G11: info->i = hyperstone.global_regs[11]; break; + case CPUINFO_INT_REGISTER + E132XS_G12: info->i = hyperstone.global_regs[12]; break; + case CPUINFO_INT_REGISTER + E132XS_G13: info->i = hyperstone.global_regs[13]; break; + case CPUINFO_INT_REGISTER + E132XS_G14: info->i = hyperstone.global_regs[14]; break; + case CPUINFO_INT_REGISTER + E132XS_G15: info->i = hyperstone.global_regs[15]; break; + case CPUINFO_INT_REGISTER + E132XS_G16: info->i = hyperstone.global_regs[16]; break; + case CPUINFO_INT_REGISTER + E132XS_G17: info->i = hyperstone.global_regs[17]; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + E132XS_SP: info->i = SP; break; + case CPUINFO_INT_REGISTER + E132XS_UB: info->i = UB; break; + case CPUINFO_INT_REGISTER + E132XS_BCR: info->i = BCR; break; + case CPUINFO_INT_REGISTER + E132XS_TPR: info->i = TPR; break; + case CPUINFO_INT_REGISTER + E132XS_TCR: info->i = TCR; break; + case CPUINFO_INT_REGISTER + E132XS_TR: info->i = TR; break; + case CPUINFO_INT_REGISTER + E132XS_WCR: info->i = WCR; break; + case CPUINFO_INT_REGISTER + E132XS_ISR: info->i = ISR; break; + case CPUINFO_INT_REGISTER + E132XS_FCR: info->i = FCR; break; + case CPUINFO_INT_REGISTER + E132XS_MCR: info->i = MCR; break; + case CPUINFO_INT_REGISTER + E132XS_G28: info->i = hyperstone.global_regs[28]; break; + case CPUINFO_INT_REGISTER + E132XS_G29: info->i = hyperstone.global_regs[29]; break; + case CPUINFO_INT_REGISTER + E132XS_G30: info->i = hyperstone.global_regs[30]; break; + case CPUINFO_INT_REGISTER + E132XS_G31: info->i = hyperstone.global_regs[31]; break; + case CPUINFO_INT_REGISTER + E132XS_CL0: info->i = hyperstone.local_regs[(0 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL1: info->i = hyperstone.local_regs[(1 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL2: info->i = hyperstone.local_regs[(2 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL3: info->i = hyperstone.local_regs[(3 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL4: info->i = hyperstone.local_regs[(4 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL5: info->i = hyperstone.local_regs[(5 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL6: info->i = hyperstone.local_regs[(6 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL7: info->i = hyperstone.local_regs[(7 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL8: info->i = hyperstone.local_regs[(8 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL9: info->i = hyperstone.local_regs[(9 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL10: info->i = hyperstone.local_regs[(10 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL11: info->i = hyperstone.local_regs[(11 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL12: info->i = hyperstone.local_regs[(12 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL13: info->i = hyperstone.local_regs[(13 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL14: info->i = hyperstone.local_regs[(14 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_CL15: info->i = hyperstone.local_regs[(15 + GET_FP) % 64]; break; + case CPUINFO_INT_REGISTER + E132XS_L0: info->i = hyperstone.local_regs[0]; break; + case CPUINFO_INT_REGISTER + E132XS_L1: info->i = hyperstone.local_regs[1]; break; + case CPUINFO_INT_REGISTER + E132XS_L2: info->i = hyperstone.local_regs[2]; break; + case CPUINFO_INT_REGISTER + E132XS_L3: info->i = hyperstone.local_regs[3]; break; + case CPUINFO_INT_REGISTER + E132XS_L4: info->i = hyperstone.local_regs[4]; break; + case CPUINFO_INT_REGISTER + E132XS_L5: info->i = hyperstone.local_regs[5]; break; + case CPUINFO_INT_REGISTER + E132XS_L6: info->i = hyperstone.local_regs[6]; break; + case CPUINFO_INT_REGISTER + E132XS_L7: info->i = hyperstone.local_regs[7]; break; + case CPUINFO_INT_REGISTER + E132XS_L8: info->i = hyperstone.local_regs[8]; break; + case CPUINFO_INT_REGISTER + E132XS_L9: info->i = hyperstone.local_regs[9]; break; + case CPUINFO_INT_REGISTER + E132XS_L10: info->i = hyperstone.local_regs[10]; break; + case CPUINFO_INT_REGISTER + E132XS_L11: info->i = hyperstone.local_regs[11]; break; + case CPUINFO_INT_REGISTER + E132XS_L12: info->i = hyperstone.local_regs[12]; break; + case CPUINFO_INT_REGISTER + E132XS_L13: info->i = hyperstone.local_regs[13]; break; + case CPUINFO_INT_REGISTER + E132XS_L14: info->i = hyperstone.local_regs[14]; break; + case CPUINFO_INT_REGISTER + E132XS_L15: info->i = hyperstone.local_regs[15]; break; + case CPUINFO_INT_REGISTER + E132XS_L16: info->i = hyperstone.local_regs[16]; break; + case CPUINFO_INT_REGISTER + E132XS_L17: info->i = hyperstone.local_regs[17]; break; + case CPUINFO_INT_REGISTER + E132XS_L18: info->i = hyperstone.local_regs[18]; break; + case CPUINFO_INT_REGISTER + E132XS_L19: info->i = hyperstone.local_regs[19]; break; + case CPUINFO_INT_REGISTER + E132XS_L20: info->i = hyperstone.local_regs[20]; break; + case CPUINFO_INT_REGISTER + E132XS_L21: info->i = hyperstone.local_regs[21]; break; + case CPUINFO_INT_REGISTER + E132XS_L22: info->i = hyperstone.local_regs[22]; break; + case CPUINFO_INT_REGISTER + E132XS_L23: info->i = hyperstone.local_regs[23]; break; + case CPUINFO_INT_REGISTER + E132XS_L24: info->i = hyperstone.local_regs[24]; break; + case CPUINFO_INT_REGISTER + E132XS_L25: info->i = hyperstone.local_regs[25]; break; + case CPUINFO_INT_REGISTER + E132XS_L26: info->i = hyperstone.local_regs[26]; break; + case CPUINFO_INT_REGISTER + E132XS_L27: info->i = hyperstone.local_regs[27]; break; + case CPUINFO_INT_REGISTER + E132XS_L28: info->i = hyperstone.local_regs[28]; break; + case CPUINFO_INT_REGISTER + E132XS_L29: info->i = hyperstone.local_regs[29]; break; + case CPUINFO_INT_REGISTER + E132XS_L30: info->i = hyperstone.local_regs[30]; break; + case CPUINFO_INT_REGISTER + E132XS_L31: info->i = hyperstone.local_regs[31]; break; + case CPUINFO_INT_REGISTER + E132XS_L32: info->i = hyperstone.local_regs[32]; break; + case CPUINFO_INT_REGISTER + E132XS_L33: info->i = hyperstone.local_regs[33]; break; + case CPUINFO_INT_REGISTER + E132XS_L34: info->i = hyperstone.local_regs[34]; break; + case CPUINFO_INT_REGISTER + E132XS_L35: info->i = hyperstone.local_regs[35]; break; + case CPUINFO_INT_REGISTER + E132XS_L36: info->i = hyperstone.local_regs[36]; break; + case CPUINFO_INT_REGISTER + E132XS_L37: info->i = hyperstone.local_regs[37]; break; + case CPUINFO_INT_REGISTER + E132XS_L38: info->i = hyperstone.local_regs[38]; break; + case CPUINFO_INT_REGISTER + E132XS_L39: info->i = hyperstone.local_regs[39]; break; + case CPUINFO_INT_REGISTER + E132XS_L40: info->i = hyperstone.local_regs[40]; break; + case CPUINFO_INT_REGISTER + E132XS_L41: info->i = hyperstone.local_regs[41]; break; + case CPUINFO_INT_REGISTER + E132XS_L42: info->i = hyperstone.local_regs[42]; break; + case CPUINFO_INT_REGISTER + E132XS_L43: info->i = hyperstone.local_regs[43]; break; + case CPUINFO_INT_REGISTER + E132XS_L44: info->i = hyperstone.local_regs[44]; break; + case CPUINFO_INT_REGISTER + E132XS_L45: info->i = hyperstone.local_regs[45]; break; + case CPUINFO_INT_REGISTER + E132XS_L46: info->i = hyperstone.local_regs[46]; break; + case CPUINFO_INT_REGISTER + E132XS_L47: info->i = hyperstone.local_regs[47]; break; + case CPUINFO_INT_REGISTER + E132XS_L48: info->i = hyperstone.local_regs[48]; break; + case CPUINFO_INT_REGISTER + E132XS_L49: info->i = hyperstone.local_regs[49]; break; + case CPUINFO_INT_REGISTER + E132XS_L50: info->i = hyperstone.local_regs[50]; break; + case CPUINFO_INT_REGISTER + E132XS_L51: info->i = hyperstone.local_regs[51]; break; + case CPUINFO_INT_REGISTER + E132XS_L52: info->i = hyperstone.local_regs[52]; break; + case CPUINFO_INT_REGISTER + E132XS_L53: info->i = hyperstone.local_regs[53]; break; + case CPUINFO_INT_REGISTER + E132XS_L54: info->i = hyperstone.local_regs[54]; break; + case CPUINFO_INT_REGISTER + E132XS_L55: info->i = hyperstone.local_regs[55]; break; + case CPUINFO_INT_REGISTER + E132XS_L56: info->i = hyperstone.local_regs[56]; break; + case CPUINFO_INT_REGISTER + E132XS_L57: info->i = hyperstone.local_regs[57]; break; + case CPUINFO_INT_REGISTER + E132XS_L58: info->i = hyperstone.local_regs[58]; break; + case CPUINFO_INT_REGISTER + E132XS_L59: info->i = hyperstone.local_regs[59]; break; + case CPUINFO_INT_REGISTER + E132XS_L60: info->i = hyperstone.local_regs[60]; break; + case CPUINFO_INT_REGISTER + E132XS_L61: info->i = hyperstone.local_regs[61]; break; + case CPUINFO_INT_REGISTER + E132XS_L62: info->i = hyperstone.local_regs[62]; break; + case CPUINFO_INT_REGISTER + E132XS_L63: info->i = hyperstone.local_regs[63]; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = hyperstone_set_info; break; + case CPUINFO_PTR_GET_CONTEXT: info->getcontext = hyperstone_get_context; break; + case CPUINFO_PTR_SET_CONTEXT: info->setcontext = hyperstone_set_context; break; + case CPUINFO_PTR_INIT: info->init = hyperstone_init; break; + case CPUINFO_PTR_RESET: info->reset = hyperstone_reset; break; + case CPUINFO_PTR_EXIT: info->exit = hyperstone_exit; break; + case CPUINFO_PTR_EXECUTE: info->execute = hyperstone_execute; break; + case CPUINFO_PTR_BURN: info->burn = NULL; break; +#ifdef MAME_DEBUG + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = hyperstone_dasm; break; +#endif /* MAME_DEBUG */ + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &hyperstone_ICount; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map = 0; break; + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_IO: info->internal_map = 0; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Hyperstone CPU"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "0.9"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Pierpaolo Prazzoli and Ryan Holtz"); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c FTE:%X FRM:%X ILC:%d FL:%d FP:%d", + GET_S ? 'S':'.', + GET_P ? 'P':'.', + GET_T ? 'T':'.', + GET_L ? 'L':'.', + GET_I ? 'I':'.', + hyperstone.global_regs[1] & 0x00040 ? '?':'.', + GET_H ? 'H':'.', + GET_M ? 'M':'.', + GET_V ? 'V':'.', + GET_N ? 'N':'.', + GET_Z ? 'Z':'.', + GET_C ? 'C':'.', + GET_FTE, + GET_FRM, + GET_ILC, + GET_FL, + GET_FP); + break; + + case CPUINFO_STR_REGISTER + E132XS_PC: sprintf(info->s, "PC :%08X", hyperstone.global_regs[0]); break; + case CPUINFO_STR_REGISTER + E132XS_SR: sprintf(info->s, "SR :%08X", hyperstone.global_regs[1]); break; + case CPUINFO_STR_REGISTER + E132XS_FER: sprintf(info->s, "FER :%08X", hyperstone.global_regs[2]); break; + case CPUINFO_STR_REGISTER + E132XS_G3: sprintf(info->s, "G3 :%08X", hyperstone.global_regs[3]); break; + case CPUINFO_STR_REGISTER + E132XS_G4: sprintf(info->s, "G4 :%08X", hyperstone.global_regs[4]); break; + case CPUINFO_STR_REGISTER + E132XS_G5: sprintf(info->s, "G5 :%08X", hyperstone.global_regs[5]); break; + case CPUINFO_STR_REGISTER + E132XS_G6: sprintf(info->s, "G6 :%08X", hyperstone.global_regs[6]); break; + case CPUINFO_STR_REGISTER + E132XS_G7: sprintf(info->s, "G7 :%08X", hyperstone.global_regs[7]); break; + case CPUINFO_STR_REGISTER + E132XS_G8: sprintf(info->s, "G8 :%08X", hyperstone.global_regs[8]); break; + case CPUINFO_STR_REGISTER + E132XS_G9: sprintf(info->s, "G9 :%08X", hyperstone.global_regs[9]); break; + case CPUINFO_STR_REGISTER + E132XS_G10: sprintf(info->s, "G10 :%08X", hyperstone.global_regs[10]); break; + case CPUINFO_STR_REGISTER + E132XS_G11: sprintf(info->s, "G11 :%08X", hyperstone.global_regs[11]); break; + case CPUINFO_STR_REGISTER + E132XS_G12: sprintf(info->s, "G12 :%08X", hyperstone.global_regs[12]); break; + case CPUINFO_STR_REGISTER + E132XS_G13: sprintf(info->s, "G13 :%08X", hyperstone.global_regs[13]); break; + case CPUINFO_STR_REGISTER + E132XS_G14: sprintf(info->s, "G14 :%08X", hyperstone.global_regs[14]); break; + case CPUINFO_STR_REGISTER + E132XS_G15: sprintf(info->s, "G15 :%08X", hyperstone.global_regs[15]); break; + case CPUINFO_STR_REGISTER + E132XS_G16: sprintf(info->s, "G16 :%08X", hyperstone.global_regs[16]); break; + case CPUINFO_STR_REGISTER + E132XS_G17: sprintf(info->s, "G17 :%08X", hyperstone.global_regs[17]); break; + case CPUINFO_STR_REGISTER + E132XS_SP: sprintf(info->s, "SP :%08X", hyperstone.global_regs[18]); break; + case CPUINFO_STR_REGISTER + E132XS_UB: sprintf(info->s, "UB :%08X", hyperstone.global_regs[19]); break; + case CPUINFO_STR_REGISTER + E132XS_BCR: sprintf(info->s, "BCR :%08X", hyperstone.global_regs[20]); break; + case CPUINFO_STR_REGISTER + E132XS_TPR: sprintf(info->s, "TPR :%08X", hyperstone.global_regs[21]); break; + case CPUINFO_STR_REGISTER + E132XS_TCR: sprintf(info->s, "TCR :%08X", hyperstone.global_regs[22]); break; + case CPUINFO_STR_REGISTER + E132XS_TR: sprintf(info->s, "TR :%08X", hyperstone.global_regs[23]); break; + case CPUINFO_STR_REGISTER + E132XS_WCR: sprintf(info->s, "WCR :%08X", hyperstone.global_regs[24]); break; + case CPUINFO_STR_REGISTER + E132XS_ISR: sprintf(info->s, "ISR :%08X", hyperstone.global_regs[25]); break; + case CPUINFO_STR_REGISTER + E132XS_FCR: sprintf(info->s, "FCR :%08X", hyperstone.global_regs[26]); break; + case CPUINFO_STR_REGISTER + E132XS_MCR: sprintf(info->s, "MCR :%08X", hyperstone.global_regs[27]); break; + case CPUINFO_STR_REGISTER + E132XS_G28: sprintf(info->s, "G28 :%08X", hyperstone.global_regs[28]); break; + case CPUINFO_STR_REGISTER + E132XS_G29: sprintf(info->s, "G29 :%08X", hyperstone.global_regs[29]); break; + case CPUINFO_STR_REGISTER + E132XS_G30: sprintf(info->s, "G30 :%08X", hyperstone.global_regs[30]); break; + case CPUINFO_STR_REGISTER + E132XS_G31: sprintf(info->s, "G31 :%08X", hyperstone.global_regs[31]); break; + case CPUINFO_STR_REGISTER + E132XS_CL0: sprintf(info->s, "CL0 :%08X", hyperstone.local_regs[(0 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL1: sprintf(info->s, "CL1 :%08X", hyperstone.local_regs[(1 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL2: sprintf(info->s, "CL2 :%08X", hyperstone.local_regs[(2 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL3: sprintf(info->s, "CL3 :%08X", hyperstone.local_regs[(3 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL4: sprintf(info->s, "CL4 :%08X", hyperstone.local_regs[(4 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL5: sprintf(info->s, "CL5 :%08X", hyperstone.local_regs[(5 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL6: sprintf(info->s, "CL6 :%08X", hyperstone.local_regs[(6 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL7: sprintf(info->s, "CL7 :%08X", hyperstone.local_regs[(7 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL8: sprintf(info->s, "CL8 :%08X", hyperstone.local_regs[(8 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL9: sprintf(info->s, "CL9 :%08X", hyperstone.local_regs[(9 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL10: sprintf(info->s, "CL10:%08X", hyperstone.local_regs[(10 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL11: sprintf(info->s, "CL11:%08X", hyperstone.local_regs[(11 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL12: sprintf(info->s, "CL12:%08X", hyperstone.local_regs[(12 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL13: sprintf(info->s, "CL13:%08X", hyperstone.local_regs[(13 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL14: sprintf(info->s, "CL14:%08X", hyperstone.local_regs[(14 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_CL15: sprintf(info->s, "CL15:%08X", hyperstone.local_regs[(15 + GET_FP) % 64]); break; + case CPUINFO_STR_REGISTER + E132XS_L0: sprintf(info->s, "L0 :%08X", hyperstone.local_regs[0]); break; + case CPUINFO_STR_REGISTER + E132XS_L1: sprintf(info->s, "L1 :%08X", hyperstone.local_regs[1]); break; + case CPUINFO_STR_REGISTER + E132XS_L2: sprintf(info->s, "L2 :%08X", hyperstone.local_regs[2]); break; + case CPUINFO_STR_REGISTER + E132XS_L3: sprintf(info->s, "L3 :%08X", hyperstone.local_regs[3]); break; + case CPUINFO_STR_REGISTER + E132XS_L4: sprintf(info->s, "L4 :%08X", hyperstone.local_regs[4]); break; + case CPUINFO_STR_REGISTER + E132XS_L5: sprintf(info->s, "L5 :%08X", hyperstone.local_regs[5]); break; + case CPUINFO_STR_REGISTER + E132XS_L6: sprintf(info->s, "L6 :%08X", hyperstone.local_regs[6]); break; + case CPUINFO_STR_REGISTER + E132XS_L7: sprintf(info->s, "L7 :%08X", hyperstone.local_regs[7]); break; + case CPUINFO_STR_REGISTER + E132XS_L8: sprintf(info->s, "L8 :%08X", hyperstone.local_regs[8]); break; + case CPUINFO_STR_REGISTER + E132XS_L9: sprintf(info->s, "L9 :%08X", hyperstone.local_regs[9]); break; + case CPUINFO_STR_REGISTER + E132XS_L10: sprintf(info->s, "L10 :%08X", hyperstone.local_regs[10]); break; + case CPUINFO_STR_REGISTER + E132XS_L11: sprintf(info->s, "L11 :%08X", hyperstone.local_regs[11]); break; + case CPUINFO_STR_REGISTER + E132XS_L12: sprintf(info->s, "L12 :%08X", hyperstone.local_regs[12]); break; + case CPUINFO_STR_REGISTER + E132XS_L13: sprintf(info->s, "L13 :%08X", hyperstone.local_regs[13]); break; + case CPUINFO_STR_REGISTER + E132XS_L14: sprintf(info->s, "L14 :%08X", hyperstone.local_regs[14]); break; + case CPUINFO_STR_REGISTER + E132XS_L15: sprintf(info->s, "L15 :%08X", hyperstone.local_regs[15]); break; + case CPUINFO_STR_REGISTER + E132XS_L16: sprintf(info->s, "L16 :%08X", hyperstone.local_regs[16]); break; + case CPUINFO_STR_REGISTER + E132XS_L17: sprintf(info->s, "L17 :%08X", hyperstone.local_regs[17]); break; + case CPUINFO_STR_REGISTER + E132XS_L18: sprintf(info->s, "L18 :%08X", hyperstone.local_regs[18]); break; + case CPUINFO_STR_REGISTER + E132XS_L19: sprintf(info->s, "L19 :%08X", hyperstone.local_regs[19]); break; + case CPUINFO_STR_REGISTER + E132XS_L20: sprintf(info->s, "L20 :%08X", hyperstone.local_regs[20]); break; + case CPUINFO_STR_REGISTER + E132XS_L21: sprintf(info->s, "L21 :%08X", hyperstone.local_regs[21]); break; + case CPUINFO_STR_REGISTER + E132XS_L22: sprintf(info->s, "L22 :%08X", hyperstone.local_regs[22]); break; + case CPUINFO_STR_REGISTER + E132XS_L23: sprintf(info->s, "L23 :%08X", hyperstone.local_regs[23]); break; + case CPUINFO_STR_REGISTER + E132XS_L24: sprintf(info->s, "L24 :%08X", hyperstone.local_regs[24]); break; + case CPUINFO_STR_REGISTER + E132XS_L25: sprintf(info->s, "L25 :%08X", hyperstone.local_regs[25]); break; + case CPUINFO_STR_REGISTER + E132XS_L26: sprintf(info->s, "L26 :%08X", hyperstone.local_regs[26]); break; + case CPUINFO_STR_REGISTER + E132XS_L27: sprintf(info->s, "L27 :%08X", hyperstone.local_regs[27]); break; + case CPUINFO_STR_REGISTER + E132XS_L28: sprintf(info->s, "L28 :%08X", hyperstone.local_regs[28]); break; + case CPUINFO_STR_REGISTER + E132XS_L29: sprintf(info->s, "L29 :%08X", hyperstone.local_regs[29]); break; + case CPUINFO_STR_REGISTER + E132XS_L30: sprintf(info->s, "L30 :%08X", hyperstone.local_regs[30]); break; + case CPUINFO_STR_REGISTER + E132XS_L31: sprintf(info->s, "L31 :%08X", hyperstone.local_regs[31]); break; + case CPUINFO_STR_REGISTER + E132XS_L32: sprintf(info->s, "L32 :%08X", hyperstone.local_regs[32]); break; + case CPUINFO_STR_REGISTER + E132XS_L33: sprintf(info->s, "L33 :%08X", hyperstone.local_regs[33]); break; + case CPUINFO_STR_REGISTER + E132XS_L34: sprintf(info->s, "L34 :%08X", hyperstone.local_regs[34]); break; + case CPUINFO_STR_REGISTER + E132XS_L35: sprintf(info->s, "L35 :%08X", hyperstone.local_regs[35]); break; + case CPUINFO_STR_REGISTER + E132XS_L36: sprintf(info->s, "L36 :%08X", hyperstone.local_regs[36]); break; + case CPUINFO_STR_REGISTER + E132XS_L37: sprintf(info->s, "L37 :%08X", hyperstone.local_regs[37]); break; + case CPUINFO_STR_REGISTER + E132XS_L38: sprintf(info->s, "L38 :%08X", hyperstone.local_regs[38]); break; + case CPUINFO_STR_REGISTER + E132XS_L39: sprintf(info->s, "L39 :%08X", hyperstone.local_regs[39]); break; + case CPUINFO_STR_REGISTER + E132XS_L40: sprintf(info->s, "L40 :%08X", hyperstone.local_regs[40]); break; + case CPUINFO_STR_REGISTER + E132XS_L41: sprintf(info->s, "L41 :%08X", hyperstone.local_regs[41]); break; + case CPUINFO_STR_REGISTER + E132XS_L42: sprintf(info->s, "L42 :%08X", hyperstone.local_regs[42]); break; + case CPUINFO_STR_REGISTER + E132XS_L43: sprintf(info->s, "L43 :%08X", hyperstone.local_regs[43]); break; + case CPUINFO_STR_REGISTER + E132XS_L44: sprintf(info->s, "L44 :%08X", hyperstone.local_regs[44]); break; + case CPUINFO_STR_REGISTER + E132XS_L45: sprintf(info->s, "L45 :%08X", hyperstone.local_regs[45]); break; + case CPUINFO_STR_REGISTER + E132XS_L46: sprintf(info->s, "L46 :%08X", hyperstone.local_regs[46]); break; + case CPUINFO_STR_REGISTER + E132XS_L47: sprintf(info->s, "L47 :%08X", hyperstone.local_regs[47]); break; + case CPUINFO_STR_REGISTER + E132XS_L48: sprintf(info->s, "L48 :%08X", hyperstone.local_regs[48]); break; + case CPUINFO_STR_REGISTER + E132XS_L49: sprintf(info->s, "L49 :%08X", hyperstone.local_regs[49]); break; + case CPUINFO_STR_REGISTER + E132XS_L50: sprintf(info->s, "L50 :%08X", hyperstone.local_regs[50]); break; + case CPUINFO_STR_REGISTER + E132XS_L51: sprintf(info->s, "L51 :%08X", hyperstone.local_regs[51]); break; + case CPUINFO_STR_REGISTER + E132XS_L52: sprintf(info->s, "L52 :%08X", hyperstone.local_regs[52]); break; + case CPUINFO_STR_REGISTER + E132XS_L53: sprintf(info->s, "L53 :%08X", hyperstone.local_regs[53]); break; + case CPUINFO_STR_REGISTER + E132XS_L54: sprintf(info->s, "L54 :%08X", hyperstone.local_regs[54]); break; + case CPUINFO_STR_REGISTER + E132XS_L55: sprintf(info->s, "L55 :%08X", hyperstone.local_regs[55]); break; + case CPUINFO_STR_REGISTER + E132XS_L56: sprintf(info->s, "L56 :%08X", hyperstone.local_regs[56]); break; + case CPUINFO_STR_REGISTER + E132XS_L57: sprintf(info->s, "L57 :%08X", hyperstone.local_regs[57]); break; + case CPUINFO_STR_REGISTER + E132XS_L58: sprintf(info->s, "L58 :%08X", hyperstone.local_regs[58]); break; + case CPUINFO_STR_REGISTER + E132XS_L59: sprintf(info->s, "L59 :%08X", hyperstone.local_regs[59]); break; + case CPUINFO_STR_REGISTER + E132XS_L60: sprintf(info->s, "L60 :%08X", hyperstone.local_regs[60]); break; + case CPUINFO_STR_REGISTER + E132XS_L61: sprintf(info->s, "L61 :%08X", hyperstone.local_regs[61]); break; + case CPUINFO_STR_REGISTER + E132XS_L62: sprintf(info->s, "L62 :%08X", hyperstone.local_regs[62]); break; + case CPUINFO_STR_REGISTER + E132XS_L63: sprintf(info->s, "L63 :%08X", hyperstone.local_regs[63]); break; + } +} + + +#if (HAS_E116T) +void e116t_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e116_4k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e116_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "E1-16T"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_E116XT) +void e116xt_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e116_8k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e116_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "E1-16XT"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_E116XS) +void e116xs_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e116_16k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e116_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "E1-16XS"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_E116XSR) +void e116xsr_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e116_16k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e116_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "E1-16XSR"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_E132N) +void e132n_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 32; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e132_4k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e132_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "E1-32N"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_E132T) +void e132t_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 32; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e132_4k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e132_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "E1-32T"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_E132XN) +void e132xn_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 32; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e132_8k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e132_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "E1-32XN"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_E132XT) +void e132xt_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 32; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e132_8k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e132_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "E1-32XT"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_E132XS) +void e132xs_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 32; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e132_16k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e132_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "E1-32XS"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_E132XSR) +void e132xsr_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 32; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e132_16k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e132_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "E1-32XSR"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_GMS30C2116) +void gms30c2116_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e116_4k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e116_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "GMS30C2116"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_GMS30C2132) +void gms30c2132_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 32; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e132_4k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e132_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "GMS30C2132"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_GMS30C2216) +void gms30c2216_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e116_8k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e116_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "GMS30C2216"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif + +#if (HAS_GMS30C2232) +void gms30c2232_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 32; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_e132_8k_iram_map; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = e132_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "GMS30C2232"); break; + + default: + hyperstone_get_info(state, info); + } +} +#endif |