📄 i8039.c
字号:
/**************************************************************************
* Intel 8039 Portable Emulator *
* *
* Copyright (C) 1997 by Mirko Buffoni *
* Based on the original work (C) 1997 by Dan Boris, an 8048 emulator *
* You are not allowed to distribute this software commercially *
* Please, notify me, if you make any changes to this file *
**************************************************************************/
#include <stdio.h>
#include <string.h>
#include "stdlib.h"
#include "I8039.h"
#include "driver.h"
#define M_RDMEM(A) I8039_RDMEM(A)
#define M_RDOP(A) I8039_RDOP(A)
#define M_RDOP_ARG(A) I8039_RDOP_ARG(A)
#define M_IN(A) I8039_In(A)
#define M_OUT(A,V) I8039_Out(A,V)
#if OLDPORTHANDLING
#define port_r(A) I8039_port_r(A)
#define port_w(A,V) I8039_port_w(A,V)
#define test_r(A) I8039_test_r(A)
#define test_w(A,V) I8039_test_w(A,V)
#define bus_r I8039_bus_r
#define bus_w(V) I8039_bus_w(V)
#else
#define port_r(A) I8039_In(I8039_p0 + A)
#define port_w(A,V) I8039_Out(I8039_p0 + A,V)
#define test_r(A) I8039_In(I8039_t0 + A)
#define test_w(A,V) I8039_Out(I8039_t0 + A,V)
#define bus_r() I8039_In(I8039_bus)
#define bus_w(V) I8039_Out(I8039_bus,V)
#endif
#define C_FLAG 0x80
#define A_FLAG 0x40
#define F_FLAG 0x20
#define B_FLAG 0x10
static I8039_Regs R;
int I8039_ICount;
static byte Old_T1;
typedef void (*opcode_fn) (void);
#define POSITIVE_EDGE_T1 (((T1-Old_T1) > 0) ? 1 : 0)
#define NEGATIVE_EDGE_T1 (((Old_T1-T1) > 0) ? 1 : 0)
#define M_Cy ((R.PSW & C_FLAG) >> 7)
#define M_Cn (!M_Cy)
#define M_Ay ((R.PSW & A_FLAG))
#define M_An (!M_Ay)
#define M_F0y ((R.PSW & F_FLAG))
#define M_F0n (!M_F0y)
#define M_By ((R.PSW & B_FLAG))
#define M_Bn (!M_By)
#define intRAM R.RAM
#define regPTR R.regPtr
#define R0 intRAM[regPTR ]
#define R1 intRAM[regPTR+1]
#define R2 intRAM[regPTR+2]
#define R3 intRAM[regPTR+3]
#define R4 intRAM[regPTR+4]
#define R5 intRAM[regPTR+5]
#define R6 intRAM[regPTR+6]
#define R7 intRAM[regPTR+7]
INLINE void CLR (byte flag) { R.PSW &= ~flag; }
INLINE void SET (byte flag) { R.PSW |= flag; }
/* Get next opcode argument and increment program counter */
INLINE unsigned M_RDMEM_OPCODE (void)
{
unsigned retval;
retval=M_RDOP_ARG(R.PC.W.w1);
R.PC.W.w1++;
return retval;
}
INLINE void push(byte d)
{
intRAM[8+R.SP++] = d;
R.SP = R.SP & 0x0f;
R.PSW = R.PSW & 0xf8;
R.PSW = R.PSW | (R.SP >> 1);
}
INLINE byte pull(void) {
R.SP = (R.SP + 15) & 0x0f; /* if (--R.SP < 0) R.SP = 15; */
R.PSW = R.PSW & 0xF8;
R.PSW = R.PSW | (R.SP >> 1);
/* regPTR = ((M_By) ? 24 : 0); regPTR should not change */
return intRAM[8+R.SP];
}
INLINE void daa_a(void)
{
byte dat;
if (((R.A & 0x0f) > 9) || (A_FLAG)) R.A += 6;
dat = R.A >> 4;
if ((dat > 9) || (C_FLAG)) { dat += 6; SET(C_FLAG); }
else CLR(C_FLAG);
R.A = (R.A & 0x0f) | (dat << 4);
}
INLINE void M_ADD(byte dat)
{
word temp;
CLR(C_FLAG | A_FLAG);
if ((R.A & 0xf) + (dat & 0xf) > 0xf) SET(A_FLAG);
temp = R.A + dat;
if (temp > 0xff) SET(C_FLAG);
R.A = temp & 0xff;
}
INLINE void M_ADDC(byte dat)
{
word temp;
CLR(A_FLAG);
if ((R.A & 0xf) + (dat & 0xf) + M_Cy > 0xf) SET(A_FLAG);
temp = R.A + dat + M_Cy;
CLR(C_FLAG);
if (temp > 0xff) SET(C_FLAG);
R.A = temp & 0xff;
}
INLINE void M_CALL(word addr)
{
push(R.PC.B.l);
push((R.PC.B.h & 0x0f) | (R.PSW & 0xf0));
R.PC.W.w1 = addr;
/*change_pc(addr);*/
}
INLINE void M_XCHD(byte addr)
{
byte dat = R.A & 0x0f;
R.A &= 0xf0;
R.A |= intRAM[addr] & 0x0f;
intRAM[addr] &= 0xf0;
intRAM[addr] |= dat;
}
INLINE void M_ILLEGAL(void)
{
}
INLINE void M_UNDEFINED(void)
{
}
#if OLDPORTHANDLING
byte I8039_port_r(byte port) { return R.p[port & 7]; }
void I8039_port_w(byte port, byte data) { R.p[port & 7] = data; }
byte I8039_test_r(byte port) { return R.t[port & 1]; }
void I8039_test_w(byte port, byte data) { R.t[port & 1] = data; }
byte I8039_bus_r(void) { return R.bus; }
void I8039_bus_w(byte data) { R.bus = data; }
#endif
static void illegal(void) { M_ILLEGAL(); }
static void add_a_n(void) { M_ADD(M_RDMEM_OPCODE()); }
static void add_a_r0(void) { M_ADD(R0); }
static void add_a_r1(void) { M_ADD(R1); }
static void add_a_r2(void) { M_ADD(R2); }
static void add_a_r3(void) { M_ADD(R3); }
static void add_a_r4(void) { M_ADD(R4); }
static void add_a_r5(void) { M_ADD(R5); }
static void add_a_r6(void) { M_ADD(R6); }
static void add_a_r7(void) { M_ADD(R7); }
static void add_a_xr0(void) { M_ADD(intRAM[R0 & 0x7f]); }
static void add_a_xr1(void) { M_ADD(intRAM[R1 & 0x7f]); }
static void adc_a_n(void) { M_ADDC(M_RDMEM_OPCODE()); }
static void adc_a_r0(void) { M_ADDC(R0); }
static void adc_a_r1(void) { M_ADDC(R1); }
static void adc_a_r2(void) { M_ADDC(R2); }
static void adc_a_r3(void) { M_ADDC(R3); }
static void adc_a_r4(void) { M_ADDC(R4); }
static void adc_a_r5(void) { M_ADDC(R5); }
static void adc_a_r6(void) { M_ADDC(R6); }
static void adc_a_r7(void) { M_ADDC(R7); }
static void adc_a_xr0(void) { M_ADDC(intRAM[R0 & 0x7f]); }
static void adc_a_xr1(void) { M_ADDC(intRAM[R1 & 0x7f]); }
static void anl_a_n(void) { R.A &= M_RDMEM_OPCODE(); }
static void anl_a_r0(void) { R.A &= R0; }
static void anl_a_r1(void) { R.A &= R1; }
static void anl_a_r2(void) { R.A &= R2; }
static void anl_a_r3(void) { R.A &= R3; }
static void anl_a_r4(void) { R.A &= R4; }
static void anl_a_r5(void) { R.A &= R5; }
static void anl_a_r6(void) { R.A &= R6; }
static void anl_a_r7(void) { R.A &= R7; }
static void anl_a_xr0(void) { R.A &= intRAM[R0 & 0x7f]; }
static void anl_a_xr1(void) { R.A &= intRAM[R1 & 0x7f]; }
static void anl_bus_n(void) { bus_w( bus_r() & M_RDMEM_OPCODE() ); }
static void anl_p1_n(void) { port_w( 1, port_r(1) & M_RDMEM_OPCODE() ); }
static void anl_p2_n(void) { port_w( 2, port_r(2) & M_RDMEM_OPCODE() ); }
static void anld_p4_a(void) { port_w( 4, port_r(4) & M_RDMEM_OPCODE() ); }
static void anld_p5_a(void) { port_w( 5, port_r(5) & M_RDMEM_OPCODE() ); }
static void anld_p6_a(void) { port_w( 6, port_r(6) & M_RDMEM_OPCODE() ); }
static void anld_p7_a(void) { port_w( 7, port_r(7) & M_RDMEM_OPCODE() ); }
static void call(void) { byte i=M_RDMEM_OPCODE(); M_CALL(i | R.A11); }
static void call_1(void) { byte i=M_RDMEM_OPCODE(); M_CALL(i | 0x100 | R.A11); }
static void call_2(void) { byte i=M_RDMEM_OPCODE(); M_CALL(i | 0x200 | R.A11); }
static void call_3(void) { byte i=M_RDMEM_OPCODE(); M_CALL(i | 0x300 | R.A11); }
static void call_4(void) { byte i=M_RDMEM_OPCODE(); M_CALL(i | 0x400 | R.A11); }
static void call_5(void) { byte i=M_RDMEM_OPCODE(); M_CALL(i | 0x500 | R.A11); }
static void call_6(void) { byte i=M_RDMEM_OPCODE(); M_CALL(i | 0x600 | R.A11); }
static void call_7(void) { byte i=M_RDMEM_OPCODE(); M_CALL(i | 0x700 | R.A11); }
static void clr_a(void) { R.A=0; }
static void clr_c(void) { CLR(C_FLAG); }
static void clr_f0(void) { CLR(F_FLAG); }
static void clr_f1(void) { R.f1 = 0; }
static void cpl_a(void) { R.A ^= 0xff; }
static void cpl_c(void) { R.PSW ^= C_FLAG; }
static void cpl_f0(void) { R.PSW ^= F_FLAG; }
static void cpl_f1(void) { R.f1 ^= 1; }
static void dec_a(void) { R.A--; }
static void dec_r0(void) { R0--; }
static void dec_r1(void) { R1--; }
static void dec_r2(void) { R2--; }
static void dec_r3(void) { R3--; }
static void dec_r4(void) { R4--; }
static void dec_r5(void) { R5--; }
static void dec_r6(void) { R6--; }
static void dec_r7(void) { R7--; }
static void dis_i(void) { R.xirq_en = 0; }
static void dis_tcnti(void) { R.tirq_en = 0; }
static void djnz_r0(void) { byte i=M_RDMEM_OPCODE(); R0--; if (R0 != 0) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void djnz_r1(void) { byte i=M_RDMEM_OPCODE(); R1--; if (R1 != 0) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void djnz_r2(void) { byte i=M_RDMEM_OPCODE(); R2--; if (R2 != 0) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void djnz_r3(void) { byte i=M_RDMEM_OPCODE(); R3--; if (R3 != 0) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void djnz_r4(void) { byte i=M_RDMEM_OPCODE(); R4--; if (R4 != 0) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void djnz_r5(void) { byte i=M_RDMEM_OPCODE(); R5--; if (R5 != 0) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void djnz_r6(void) { byte i=M_RDMEM_OPCODE(); R6--; if (R6 != 0) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void djnz_r7(void) { byte i=M_RDMEM_OPCODE(); R7--; if (R7 != 0) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void en_i(void) { R.xirq_en = 1; }
static void en_tcnti(void) { R.tirq_en = 1; }
static void ento_clk(void) { M_UNDEFINED(); }
static void in_a_p1(void) { R.A = port_r(1); }
static void in_a_p2(void) { R.A = port_r(2); }
static void ins_a_bus(void) { R.A = bus_r(); }
static void inc_a(void) { R.A++; }
static void inc_r0(void) { R0++; }
static void inc_r1(void) { R1++; }
static void inc_r2(void) { R2++; }
static void inc_r3(void) { R3++; }
static void inc_r4(void) { R4++; }
static void inc_r5(void) { R5++; }
static void inc_r6(void) { R6++; }
static void inc_r7(void) { R7++; }
static void inc_xr0(void) { intRAM[R0 & 0x7F]++; }
static void inc_xr1(void) { intRAM[R1 & 0x7F]++; }
/* static void jmp(void) { byte i=M_RDOP(R.PC.W.w1); R.PC.W.w1 = i | R.A11; }
*/
static void jmp(void)
{
byte i=M_RDOP(R.PC.W.w1);
word oldpc,newpc;
oldpc = R.PC.W.w1-1;
R.PC.W.w1 = i | R.A11; /*change_pc(R.PC.W.w1);*/
newpc = R.PC.W.w1;
if (newpc == oldpc) { if (I8039_ICount > 0) I8039_ICount = 0; } /* speed up busy loop */
else if (newpc == oldpc-1 && M_RDOP(newpc) == 0x00) /* NOP - Gyruss */
{ if (I8039_ICount > 0) I8039_ICount = 0; }
}
static void jmp_1(void) { byte i=M_RDOP(R.PC.W.w1); R.PC.W.w1 = i | 0x100 | R.A11; /*change_pc(R.PC.W.w1);*/ }
static void jmp_2(void) { byte i=M_RDOP(R.PC.W.w1); R.PC.W.w1 = i | 0x200 | R.A11; /*change_pc(R.PC.W.w1);*/ }
static void jmp_3(void) { byte i=M_RDOP(R.PC.W.w1); R.PC.W.w1 = i | 0x300 | R.A11; /*change_pc(R.PC.W.w1);*/ }
static void jmp_4(void) { byte i=M_RDOP(R.PC.W.w1); R.PC.W.w1 = i | 0x400 | R.A11; /*change_pc(R.PC.W.w1);*/ }
static void jmp_5(void) { byte i=M_RDOP(R.PC.W.w1); R.PC.W.w1 = i | 0x500 | R.A11; /*change_pc(R.PC.W.w1);*/ }
static void jmp_6(void) { byte i=M_RDOP(R.PC.W.w1); R.PC.W.w1 = i | 0x600 | R.A11; /*change_pc(R.PC.W.w1);*/ }
static void jmp_7(void) { byte i=M_RDOP(R.PC.W.w1); R.PC.W.w1 = i | 0x700 | R.A11; /*change_pc(R.PC.W.w1);*/ }
static void jmpp_xa(void) { word addr = (R.PC.W.w1 & 0xf00) | R.A; R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | M_RDMEM(addr); /*change_pc(R.PC.W.w1);*/ }
static void jb_0(void) { byte i=M_RDMEM_OPCODE(); if (R.A & 0x01) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jb_1(void) { byte i=M_RDMEM_OPCODE(); if (R.A & 0x02) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jb_2(void) { byte i=M_RDMEM_OPCODE(); if (R.A & 0x04) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jb_3(void) { byte i=M_RDMEM_OPCODE(); if (R.A & 0x08) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jb_4(void) { byte i=M_RDMEM_OPCODE(); if (R.A & 0x10) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jb_5(void) { byte i=M_RDMEM_OPCODE(); if (R.A & 0x20) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jb_6(void) { byte i=M_RDMEM_OPCODE(); if (R.A & 0x40) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jb_7(void) { byte i=M_RDMEM_OPCODE(); if (R.A & 0x80) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jf0(void) { byte i=M_RDMEM_OPCODE(); if (M_F0y) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jf_1(void) { byte i=M_RDMEM_OPCODE(); if (R.f1) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jnc(void) { byte i=M_RDMEM_OPCODE(); if (M_Cn) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jc(void) { byte i=M_RDMEM_OPCODE(); if (M_Cy) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jni(void) { byte i=M_RDMEM_OPCODE(); if (R.pending_irq == I8039_EXT_INT) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jnt_0(void) { byte i=M_RDMEM_OPCODE(); if (!test_r(0)) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jt_0(void) { byte i=M_RDMEM_OPCODE(); if (test_r(0)) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jnt_1(void) { byte i=M_RDMEM_OPCODE(); if (!test_r(1)) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jt_1(void) { byte i=M_RDMEM_OPCODE(); if (test_r(1)) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jnz(void) { byte i=M_RDMEM_OPCODE(); if (R.A != 0) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jz(void) { byte i=M_RDMEM_OPCODE(); if (R.A == 0) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ } }
static void jtf(void) { byte i=M_RDMEM_OPCODE(); if (R.t_flag) { R.PC.W.w1 = (R.PC.W.w1 & 0xf00) | i; /*change_pc(R.PC.W.w1);*/ R.t_flag = 0; } }
static void mov_a_n(void) { R.A = M_RDMEM_OPCODE(); }
static void mov_a_r0(void) { R.A = R0; }
static void mov_a_r1(void) { R.A = R1; }
static void mov_a_r2(void) { R.A = R2; }
static void mov_a_r3(void) { R.A = R3; }
static void mov_a_r4(void) { R.A = R4; }
static void mov_a_r5(void) { R.A = R5; }
static void mov_a_r6(void) { R.A = R6; }
static void mov_a_r7(void) { R.A = R7; }
static void mov_a_psw(void) { R.A = R.PSW; }
static void mov_a_xr0(void) { R.A = intRAM[R0 & 0x7f]; }
static void mov_a_xr1(void) { R.A = intRAM[R1 & 0x7f]; }
static void mov_r0_a(void) { R0 = R.A; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -