Merge branch 'master' of https://github.com/86Box/86Box
This commit is contained in:
@@ -126,7 +126,7 @@ get_addr(headland_t *dev, uint32_t addr, headland_mr_t *mr)
|
||||
else
|
||||
addr |= (mr->mr & 0x180) << 12;
|
||||
}
|
||||
} else if ((mr == NULL) && ((dev->cr[0] & 4) == 0) && (mem_size >= 1024) && (addr >= 0x100000))
|
||||
} else if (((mr == NULL) || ((mr != NULL) && !mr->valid)) && ((dev->cr[0] & 4) == 0) && (mem_size >= 1024) && (addr >= 0x100000))
|
||||
addr -= 0x60000;
|
||||
|
||||
return addr;
|
||||
@@ -134,31 +134,42 @@ get_addr(headland_t *dev, uint32_t addr, headland_mr_t *mr)
|
||||
|
||||
|
||||
static void
|
||||
set_global_EMS_state(headland_t *dev, int state)
|
||||
hl_ems_disable(headland_t *dev, uint8_t mar, uint32_t base_addr, uint8_t indx)
|
||||
{
|
||||
mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], ram + base_addr);
|
||||
mem_mapping_disable(&dev->ems_mapping[mar & 0x3f]);
|
||||
if (indx < 24) {
|
||||
mem_set_mem_state(base_addr, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
mem_mapping_enable(&dev->upper_mapping[indx]);
|
||||
} else
|
||||
mem_set_mem_state(base_addr, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hl_ems_update(headland_t *dev, uint8_t mar)
|
||||
{
|
||||
uint32_t base_addr, virt_addr;
|
||||
int i;
|
||||
uint8_t indx = mar & 0x1f;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
base_addr = (i + 16) << 14;
|
||||
if (i >= 24)
|
||||
base_addr += 0x20000;
|
||||
if ((state & 2) && (dev->ems_mr[((state & 1) << 5) | i].mr & 0x200)) {
|
||||
virt_addr = get_addr(dev, base_addr, &dev->ems_mr[((state & 1) << 5) | i]);
|
||||
if (i < 24)
|
||||
mem_mapping_disable(&dev->upper_mapping[i]);
|
||||
mem_mapping_disable(&dev->ems_mapping[(((state ^ 1) & 1) << 5) | i]);
|
||||
mem_mapping_enable(&dev->ems_mapping[((state & 1) << 5) | i]);
|
||||
base_addr = (indx + 16) << 14;
|
||||
if (indx >= 24)
|
||||
base_addr += 0x20000;
|
||||
/* Do not disable unless the MAR at the correct context is locally disabled or
|
||||
EMS is globally disabled. */
|
||||
if (!(dev->cr[0] & 2) || !(dev->ems_mr[(mar & 0x1f) | ((dev->cr[0] & 1) << 5)].mr & 0x200))
|
||||
hl_ems_disable(dev, mar, base_addr, indx);
|
||||
if ((dev->cr[0] & 2) && ((dev->cr[0] & 1) == ((mar & 0x20) >> 5))) {
|
||||
if (dev->ems_mr[mar & 0x3f].mr & 0x200) {
|
||||
mem_set_mem_state(base_addr, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
virt_addr = get_addr(dev, base_addr, &dev->ems_mr[mar & 0x3f]);
|
||||
if (indx < 24)
|
||||
mem_mapping_disable(&dev->upper_mapping[indx]);
|
||||
if (virt_addr < ((uint32_t)mem_size << 10))
|
||||
mem_mapping_set_exec(&dev->ems_mapping[((state & 1) << 5) | i], ram + virt_addr);
|
||||
mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], ram + virt_addr);
|
||||
else
|
||||
mem_mapping_set_exec(&dev->ems_mapping[((state & 1) << 5) | i], NULL);
|
||||
} else {
|
||||
mem_mapping_set_exec(&dev->ems_mapping[((state & 1) << 5) | i], ram + base_addr);
|
||||
mem_mapping_disable(&dev->ems_mapping[(((state ^ 1) & 1) << 5) | i]);
|
||||
mem_mapping_disable(&dev->ems_mapping[((state & 1) << 5) | i]);
|
||||
if (i < 24)
|
||||
mem_mapping_enable(&dev->upper_mapping[i]);
|
||||
mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], NULL);
|
||||
mem_mapping_enable(&dev->ems_mapping[mar & 0x3f]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,6 +177,16 @@ set_global_EMS_state(headland_t *dev, int state)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_global_EMS_state(headland_t *dev, int state)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
hl_ems_update(dev, i);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
memmap_state_update(headland_t *dev)
|
||||
{
|
||||
@@ -176,7 +197,7 @@ memmap_state_update(headland_t *dev)
|
||||
addr = get_addr(dev, 0x40000 + (i << 14), NULL);
|
||||
mem_mapping_set_exec(&dev->upper_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL);
|
||||
}
|
||||
mem_set_mem_state(0xA0000, 0x40000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
// mem_set_mem_state(0xA0000, 0x40000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
if (mem_size > 640) {
|
||||
if ((dev->cr[0] & 4) == 0) {
|
||||
mem_mapping_set_addr(&dev->mid_mapping, 0x100000, mem_size > 1024 ? 0x60000 : (mem_size - 640) << 10);
|
||||
@@ -203,8 +224,7 @@ static void
|
||||
hl_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
headland_t *dev = (headland_t *)priv;
|
||||
uint32_t base_addr, virt_addr;
|
||||
uint8_t old_val, indx;
|
||||
uint8_t old_val;
|
||||
|
||||
switch(addr) {
|
||||
case 0x0022:
|
||||
@@ -213,6 +233,7 @@ hl_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
case 0x0023:
|
||||
old_val = dev->regs[dev->indx];
|
||||
|
||||
if ((dev->indx == 0xc1) && !is486)
|
||||
val = 0;
|
||||
dev->regs[dev->indx] = val;
|
||||
@@ -231,21 +252,7 @@ hl_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
case 0x01ec:
|
||||
dev->ems_mr[dev->ems_mar & 0x3f].mr = val | 0xff00;
|
||||
indx = dev->ems_mar & 0x1f;
|
||||
base_addr = (indx + 16) << 14;
|
||||
if (indx >= 24)
|
||||
base_addr += 0x20000;
|
||||
if ((dev->cr[0] & 2) && ((dev->cr[0] & 1) == ((dev->ems_mar & 0x20) >> 5))) {
|
||||
virt_addr = get_addr(dev, base_addr, &dev->ems_mr[dev->ems_mar & 0x3F]);
|
||||
if (indx < 24)
|
||||
mem_mapping_disable(&dev->upper_mapping[indx]);
|
||||
if (virt_addr < ((uint32_t)mem_size << 10))
|
||||
mem_mapping_set_exec(&dev->ems_mapping[dev->ems_mar & 0x3f], ram + virt_addr);
|
||||
else
|
||||
mem_mapping_set_exec(&dev->ems_mapping[dev->ems_mar & 0x3f], NULL);
|
||||
mem_mapping_enable(&dev->ems_mapping[dev->ems_mar & 0x3f]);
|
||||
flushmmucache();
|
||||
}
|
||||
hl_ems_update(dev, dev->ems_mar & 0x3f);
|
||||
if (dev->ems_mar & 0x80)
|
||||
dev->ems_mar++;
|
||||
break;
|
||||
@@ -313,34 +320,11 @@ static void
|
||||
hl_writew(uint16_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
headland_t *dev = (headland_t *)priv;
|
||||
uint32_t base_addr, virt_addr;
|
||||
uint8_t indx;
|
||||
|
||||
switch(addr) {
|
||||
case 0x01ec:
|
||||
dev->ems_mr[dev->ems_mar & 0x3f].mr = val;
|
||||
indx = dev->ems_mar & 0x1f;
|
||||
base_addr = (indx + 16) << 14;
|
||||
if (indx >= 24)
|
||||
base_addr += 0x20000;
|
||||
if ((dev->cr[0] & 2) && (dev->cr[0] & 1) == ((dev->ems_mar & 0x20) >> 5)) {
|
||||
if (val & 0x200) {
|
||||
virt_addr = get_addr(dev, base_addr, &dev->ems_mr[dev->ems_mar & 0x3f]);
|
||||
if (indx < 24)
|
||||
mem_mapping_disable(&dev->upper_mapping[indx]);
|
||||
if (virt_addr < ((uint32_t)mem_size << 10))
|
||||
mem_mapping_set_exec(&dev->ems_mapping[dev->ems_mar & 0x3f], ram + virt_addr);
|
||||
else
|
||||
mem_mapping_set_exec(&dev->ems_mapping[dev->ems_mar & 0x3f], NULL);
|
||||
mem_mapping_enable(&dev->ems_mapping[dev->ems_mar & 0x3f]);
|
||||
} else {
|
||||
mem_mapping_set_exec(&dev->ems_mapping[dev->ems_mar & 0x3f], ram + base_addr);
|
||||
mem_mapping_disable(&dev->ems_mapping[dev->ems_mar & 0x3f]);
|
||||
if (indx < 24)
|
||||
mem_mapping_enable(&dev->upper_mapping[indx]);
|
||||
}
|
||||
flushmmucache();
|
||||
}
|
||||
hl_ems_update(dev, dev->ems_mar & 0x3f);
|
||||
if (dev->ems_mar & 0x80)
|
||||
dev->ems_mar++;
|
||||
break;
|
||||
@@ -549,14 +533,12 @@ headland_init(const device_t *info)
|
||||
} else
|
||||
dev->cr[4] = 0x00;
|
||||
|
||||
io_sethandler(0x01ec, 1,
|
||||
io_sethandler(0x01ec, 4,
|
||||
hl_read,hl_readw,NULL, hl_write,hl_writew,NULL, dev);
|
||||
|
||||
io_sethandler(0x01ed, 3, hl_read,NULL,NULL, hl_write,NULL,NULL, dev);
|
||||
|
||||
dev->ems_mr[i].valid = 0;
|
||||
dev->ems_mr[i].mr = 0xff;
|
||||
dev->ems_mr[i].headland = dev;
|
||||
dev->null_mr.valid = 0;
|
||||
dev->null_mr.mr = 0xff;
|
||||
dev->null_mr.headland = dev;
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
dev->ems_mr[i].valid = 1;
|
||||
@@ -607,7 +589,8 @@ headland_init(const device_t *info)
|
||||
mem_read_b, mem_read_w, mem_read_l,
|
||||
mem_write_b, mem_write_w, mem_write_l,
|
||||
ram + (((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14),
|
||||
0, &dev->ems_mr[i]);
|
||||
MEM_MAPPING_INTERNAL, &dev->ems_mr[i]);
|
||||
mem_mapping_disable(&dev->ems_mapping[i]);
|
||||
}
|
||||
|
||||
memmap_state_update(dev);
|
||||
|
||||
@@ -20,6 +20,14 @@ static struct
|
||||
void codegen_accumulate(int acc_reg, int delta)
|
||||
{
|
||||
acc_regs[acc_reg].count += delta;
|
||||
|
||||
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
|
||||
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t) (uintptr_t) &(acycs));
|
||||
addlong(-delta);
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_accumulate_flush(void)
|
||||
|
||||
@@ -14,12 +14,19 @@ static struct
|
||||
} acc_regs[] =
|
||||
{
|
||||
[ACCREG_ins] = {0, (uintptr_t) &(ins)},
|
||||
[ACCREG_cycles] = {0, (uintptr_t) &(cycles)},
|
||||
[ACCREG_cycles] = {0, (uintptr_t) &(cycles)}
|
||||
};
|
||||
|
||||
void codegen_accumulate(int acc_reg, int delta)
|
||||
{
|
||||
acc_regs[acc_reg].count += delta;
|
||||
|
||||
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
|
||||
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t) (uintptr_t) &(acycs));
|
||||
addlong((uintptr_t) -delta);
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_accumulate_flush(void)
|
||||
|
||||
@@ -1095,6 +1095,14 @@ generate_call:
|
||||
codegen_block_full_ins++;
|
||||
codegen_endpc = (cs + cpu_state.pc) + 8;
|
||||
|
||||
/* Check for interrupts. */
|
||||
call(block, (uintptr_t)int_check);
|
||||
|
||||
addbyte(0x85); /*OR %eax, %eax*/
|
||||
addbyte(0xc0);
|
||||
addbyte(0x0F); addbyte(0x85); /*JNZ 0*/
|
||||
addlong((uint32_t)(uintptr_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(uintptr_t)(&block->data[block_pos + 4]));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1172,6 +1180,14 @@ generate_call:
|
||||
addbyte(0x0F); addbyte(0x85); /*JNZ 0*/
|
||||
addlong((uint32_t)(uintptr_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(uintptr_t)(&block->data[block_pos + 4]));
|
||||
|
||||
/* Check for interrupts. */
|
||||
call(block, (uintptr_t)int_check);
|
||||
|
||||
addbyte(0x85); /*OR %eax, %eax*/
|
||||
addbyte(0xc0);
|
||||
addbyte(0x0F); addbyte(0x85); /*JNZ 0*/
|
||||
addlong((uint32_t)(uintptr_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(uintptr_t)(&block->data[block_pos + 4]));
|
||||
|
||||
codegen_endpc = (cs + cpu_state.pc) + 8;
|
||||
}
|
||||
|
||||
|
||||
@@ -2062,6 +2062,15 @@ generate_call:
|
||||
codegen_block_full_ins++;
|
||||
codegen_endpc = (cs + cpu_state.pc) + 8;
|
||||
|
||||
/* Check for interrupts. */
|
||||
addbyte(0xE8); /*CALL*/
|
||||
addlong(((uint8_t *)int_check - (uint8_t *)(&block->data[block_pos + 4])));
|
||||
|
||||
addbyte(0x09); /*OR %eax, %eax*/
|
||||
addbyte(0xc0);
|
||||
addbyte(0x0F); addbyte(0x85); /*JNZ 0*/
|
||||
addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4]));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2150,6 +2159,15 @@ generate_call:
|
||||
addbyte(0x0F); addbyte(0x85); /*JNZ 0*/
|
||||
addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4]));
|
||||
|
||||
/* Check for interrupts. */
|
||||
addbyte(0xE8); /*CALL*/
|
||||
addlong(((uint8_t *)int_check - (uint8_t *)(&block->data[block_pos + 4])));
|
||||
|
||||
addbyte(0x09); /*OR %eax, %eax*/
|
||||
addbyte(0xc0);
|
||||
addbyte(0x0F); addbyte(0x85); /*JNZ 0*/
|
||||
addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4]));
|
||||
|
||||
codegen_endpc = (cs + cpu_state.pc) + 8;
|
||||
}
|
||||
|
||||
|
||||
@@ -599,8 +599,8 @@ generate_call:
|
||||
|
||||
codegen_timing_opcode(opcode, fetchdat, op_32, op_pc);
|
||||
|
||||
codegen_accumulate(ACCREG_ins, 1);
|
||||
codegen_accumulate(ACCREG_cycles, -codegen_block_cycles);
|
||||
codegen_accumulate(ir, ACCREG_ins, 1);
|
||||
codegen_accumulate(ir, ACCREG_cycles, -codegen_block_cycles);
|
||||
codegen_block_cycles = 0;
|
||||
|
||||
if ((op_table == x86_dynarec_opcodes &&
|
||||
@@ -620,10 +620,10 @@ generate_call:
|
||||
codegen_timing_jump_cycles();
|
||||
|
||||
if (jump_cycles)
|
||||
codegen_accumulate(ACCREG_cycles, -jump_cycles);
|
||||
codegen_accumulate(ir, ACCREG_cycles, -jump_cycles);
|
||||
codegen_accumulate_flush(ir);
|
||||
if (jump_cycles)
|
||||
codegen_accumulate(ACCREG_cycles, jump_cycles);
|
||||
codegen_accumulate(ir, ACCREG_cycles, jump_cycles);
|
||||
}
|
||||
|
||||
if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f)
|
||||
@@ -696,6 +696,9 @@ generate_call:
|
||||
|
||||
block->ins++;
|
||||
|
||||
/* Check for interrupts. */
|
||||
uop_CALL_INSTRUCTION_FUNC(ir, int_check);
|
||||
|
||||
if (block->ins >= MAX_INSTRUCTION_COUNT)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
@@ -756,6 +759,8 @@ generate_call:
|
||||
uop_MOV_IMM(ir, IREG_ssegs, op_ssegs);
|
||||
uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat);
|
||||
uop_CALL_INSTRUCTION_FUNC(ir, op);
|
||||
/* Check for interrupts. */
|
||||
uop_CALL_INSTRUCTION_FUNC(ir, int_check);
|
||||
codegen_mark_code_present(block, cs+cpu_state.pc, 8);
|
||||
|
||||
last_op_32 = op_32;
|
||||
|
||||
@@ -17,9 +17,13 @@ static struct
|
||||
[ACCREG_cycles] = {0, IREG_cycles},
|
||||
};
|
||||
|
||||
void codegen_accumulate(int acc_reg, int delta)
|
||||
void codegen_accumulate(ir_data_t *ir, int acc_reg, int delta)
|
||||
{
|
||||
acc_regs[acc_reg].count += delta;
|
||||
|
||||
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
|
||||
uop_ADD_IMM(ir, IREG_acycs, IREG_acycs, -delta);
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_accumulate_flush(ir_data_t *ir)
|
||||
|
||||
@@ -8,6 +8,6 @@ enum
|
||||
|
||||
struct ir_data_t;
|
||||
|
||||
void codegen_accumulate(int acc_reg, int delta);
|
||||
void codegen_accumulate(struct ir_data_t *ir, int acc_reg, int delta);
|
||||
void codegen_accumulate_flush(struct ir_data_t *ir);
|
||||
void codegen_accumulate_reset();
|
||||
|
||||
@@ -782,7 +782,7 @@ void codegen_block_end()
|
||||
void codegen_block_end_recompile(codeblock_t *block)
|
||||
{
|
||||
codegen_timing_block_end();
|
||||
codegen_accumulate(ACCREG_cycles, -codegen_block_cycles);
|
||||
codegen_accumulate(ir_data, ACCREG_cycles, -codegen_block_cycles);
|
||||
|
||||
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||
block_dirty_list_remove(block);
|
||||
|
||||
@@ -180,6 +180,8 @@ struct
|
||||
|
||||
[IREG_temp0d] = {REG_DOUBLE, (void *)40, REG_FP, REG_VOLATILE},
|
||||
[IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP, REG_VOLATILE},
|
||||
|
||||
[IREG_acycs] = {REG_DWORD, &acycs, REG_INTEGER, REG_PERMANENT}
|
||||
};
|
||||
|
||||
void codegen_reg_mark_as_required()
|
||||
|
||||
@@ -133,7 +133,9 @@ enum
|
||||
IREG_GS_limit_high = 86,
|
||||
IREG_SS_limit_high = 87,
|
||||
|
||||
IREG_COUNT = 88,
|
||||
IREG_acycs = 88,
|
||||
|
||||
IREG_COUNT = 89,
|
||||
|
||||
IREG_INVALID = 255,
|
||||
|
||||
|
||||
@@ -276,30 +276,50 @@ static void prefetch_flush()
|
||||
static int cycles_main = 0, cycles_old = 0;
|
||||
static uint64_t tsc_old = 0;
|
||||
|
||||
int acycs = 0;
|
||||
|
||||
void update_tsc(void)
|
||||
{
|
||||
int cycdiff;
|
||||
uint64_t delta;
|
||||
|
||||
cycdiff = cycles_old - cycles;
|
||||
if (inrecomp)
|
||||
cycdiff += acycs;
|
||||
|
||||
delta = tsc - tsc_old;
|
||||
if (delta > 0) {
|
||||
/* TSC has changed, this means interim timer processing has happened,
|
||||
see how much we still need to add. */
|
||||
cycdiff -= delta;
|
||||
if (cycdiff > 0)
|
||||
tsc += cycdiff;
|
||||
} else {
|
||||
/* TSC has not changed. */
|
||||
tsc += cycdiff;
|
||||
}
|
||||
|
||||
if (cycdiff > 0)
|
||||
tsc += cycdiff;
|
||||
|
||||
if (cycdiff > 0) {
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
|
||||
timer_process();
|
||||
}
|
||||
}
|
||||
|
||||
int int_check(void)
|
||||
{
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
|
||||
if (trap)
|
||||
return 1;
|
||||
else if (smi_line)
|
||||
return 1;
|
||||
else if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
else if ((cpu_state.flags & I_FLAG) && pic_intpending)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void exec386_dynarec(int cycs)
|
||||
{
|
||||
int vector;
|
||||
@@ -313,6 +333,7 @@ void exec386_dynarec(int cycs)
|
||||
|
||||
int cyc_period = cycs / 2000; /*5us*/
|
||||
|
||||
acycs = 0;
|
||||
cycles_main += cycs;
|
||||
while (cycles_main > 0)
|
||||
{
|
||||
@@ -534,6 +555,7 @@ void exec386_dynarec(int cycs)
|
||||
|
||||
inrecomp=1;
|
||||
code();
|
||||
acycs = 0;
|
||||
inrecomp=0;
|
||||
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
|
||||
@@ -61,8 +61,6 @@
|
||||
#endif
|
||||
#include "x87_timings.h"
|
||||
|
||||
/*#define ENABLE_CPU_LOG 1*/
|
||||
|
||||
static void cpu_write(uint16_t addr, uint8_t val, void *priv);
|
||||
static uint8_t cpu_read(uint16_t addr, void *priv);
|
||||
|
||||
@@ -362,6 +360,8 @@ cpu_set(void)
|
||||
cpu_effective = cpu;
|
||||
cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective];
|
||||
|
||||
acycs = 0;
|
||||
|
||||
cpu_alt_reset = 0;
|
||||
unmask_a20_in_smm = 0;
|
||||
|
||||
|
||||
@@ -503,6 +503,8 @@ extern int timing_misaligned;
|
||||
extern int in_sys, unmask_a20_in_smm;
|
||||
extern uint32_t old_rammask;
|
||||
|
||||
extern int acycs;
|
||||
|
||||
extern uint16_t cpu_fast_off_count, cpu_fast_off_val;
|
||||
extern uint32_t cpu_fast_off_flags;
|
||||
|
||||
@@ -599,4 +601,6 @@ extern const char *fpu_get_internal_name(int machine, int cpu_manufacturer, int
|
||||
extern const char *fpu_get_name_from_index(int machine, int cpu_manufacturer, int cpu, int c);
|
||||
extern int fpu_get_type_from_index(int machine, int cpu_manufacturer, int cpu, int c);
|
||||
|
||||
extern int int_check();
|
||||
|
||||
#endif /*EMU_CPU_H*/
|
||||
|
||||
@@ -2479,6 +2479,16 @@ const device_t keyboard_ps2_ps1_device = {
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_ps2_ps1_pci_device = {
|
||||
"PS/2 Keyboard (IBM PS/1)",
|
||||
DEVICE_PCI,
|
||||
KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1,
|
||||
kbd_init,
|
||||
kbd_close,
|
||||
kbd_reset,
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_ps2_xi8088_device = {
|
||||
"PS/2 Keyboard (Xi8088)",
|
||||
0,
|
||||
|
||||
@@ -73,6 +73,7 @@ extern const device_t keyboard_at_ami_device;
|
||||
extern const device_t keyboard_at_toshiba_device;
|
||||
extern const device_t keyboard_ps2_device;
|
||||
extern const device_t keyboard_ps2_ps1_device;
|
||||
extern const device_t keyboard_ps2_ps1_pci_device;
|
||||
extern const device_t keyboard_ps2_ps2_device;
|
||||
extern const device_t keyboard_ps2_xi8088_device;
|
||||
extern const device_t keyboard_ps2_ami_device;
|
||||
|
||||
@@ -309,11 +309,9 @@ extern int machine_at_excalibur_init(const machine_t *);
|
||||
|
||||
extern int machine_at_batman_init(const machine_t *);
|
||||
extern int machine_at_ambradp60_init(const machine_t *);
|
||||
#if defined(DEV_BRANCH) && defined(USE_VPP60)
|
||||
extern int machine_at_valuepointp60_init(const machine_t *);
|
||||
#endif
|
||||
#if defined(DEV_BRANCH) && defined(USE_DELLS4)
|
||||
extern int machine_at_opti560l_init(const machine_t *);
|
||||
#if defined(DEV_BRANCH) && defined(USE_DELLXP60)
|
||||
extern int machine_at_dellxp60_init(const machine_t *);
|
||||
#endif
|
||||
extern int machine_at_p5mp3_init(const machine_t *);
|
||||
@@ -505,7 +503,9 @@ extern int machine_xt_jukopc_init(const machine_t *);
|
||||
extern int machine_xt_open_xt_init(const machine_t *);
|
||||
extern int machine_xt_pxxt_init(const machine_t *);
|
||||
|
||||
extern int machine_xt_hed919_init(const machine_t *);
|
||||
#if defined(DEV_BRANCH) && defined(USE_HEDAKA)
|
||||
extern int machine_xt_hed919_init(const machine_t *);
|
||||
#endif
|
||||
|
||||
/* m_xt_compaq.c */
|
||||
extern int machine_xt_compaq_init(const machine_t *);
|
||||
|
||||
@@ -141,6 +141,8 @@ extern const device_t *network_card_getdevice(int);
|
||||
extern void network_set_wait(int wait);
|
||||
extern int network_get_wait(void);
|
||||
|
||||
extern void network_timer_stop(void);
|
||||
|
||||
extern void network_queue_put(int tx, void *priv, uint8_t *data, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -140,7 +140,6 @@ machine_at_ambradp60_init(const machine_t *model)
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_VPP60)
|
||||
int
|
||||
machine_at_valuepointp60_init(const machine_t *model)
|
||||
{
|
||||
@@ -155,23 +154,22 @@ machine_at_valuepointp60_init(const machine_t *model)
|
||||
machine_at_common_init(model);
|
||||
device_add(&ide_pci_2ch_device);
|
||||
|
||||
pci_init(PCI_CONFIG_TYPE_2);
|
||||
pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING);
|
||||
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0);
|
||||
pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4);
|
||||
pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4);
|
||||
pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4);
|
||||
pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
|
||||
device_add(&keyboard_ps2_intel_ami_pci_device);
|
||||
device_add(&sio_zb_device);
|
||||
device_add(&i82091aa_device);
|
||||
device_add(&keyboard_ps2_ps1_pci_device);
|
||||
device_add(&sio_device);
|
||||
device_add(&fdc37c665_device);
|
||||
device_add(&intel_flash_bxt_ami_device);
|
||||
|
||||
device_add(&i430lx_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
@@ -217,6 +215,7 @@ at_pb520r_get_device(void)
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_DELLS4)
|
||||
int
|
||||
machine_at_opti560l_init(const machine_t *model)
|
||||
{
|
||||
@@ -248,7 +247,6 @@ machine_at_opti560l_init(const machine_t *model)
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_DELLXP60)
|
||||
int
|
||||
machine_at_dellxp60_init(const machine_t *model) // Doesn't like the regular SMC 665
|
||||
{
|
||||
|
||||
@@ -254,6 +254,8 @@ machine_xt_open_xt_init(const machine_t *model)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_HEDAKA)
|
||||
int
|
||||
machine_xt_hed919_init(const machine_t *model)
|
||||
{
|
||||
@@ -272,6 +274,8 @@ machine_xt_hed919_init(const machine_t *model)
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
machine_xt_pxxt_init(const machine_t *model)
|
||||
|
||||
@@ -890,7 +890,7 @@ machine_xt_t1000_init(const machine_t *model)
|
||||
}
|
||||
mem_mapping_add(&t1000.rom_mapping, 0xa0000, 0x10000,
|
||||
t1000_read_rom,t1000_read_romw,t1000_read_roml,
|
||||
NULL,NULL,NULL, NULL, MEM_MAPPING_INTERNAL, &t1000);
|
||||
NULL,NULL,NULL, NULL, MEM_MAPPING_EXTERNAL, &t1000);
|
||||
mem_mapping_disable(&t1000.rom_mapping);
|
||||
|
||||
/* Map the EMS page frame */
|
||||
@@ -986,7 +986,7 @@ machine_xt_t1200_init(const machine_t *model)
|
||||
0x000f0000, 2048,
|
||||
read_t1200_nvram, NULL, NULL,
|
||||
write_t1200_nvram, NULL, NULL,
|
||||
NULL, 0, &t1000);
|
||||
NULL, MEM_MAPPING_EXTERNAL, &t1000);
|
||||
|
||||
pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt);
|
||||
device_add(&keyboard_xt_device);
|
||||
|
||||
@@ -123,7 +123,9 @@ const machine_t machines[] = {
|
||||
#endif
|
||||
|
||||
/* 286 XT machines */
|
||||
#if defined(DEV_BRANCH) && defined(USE_HEDAKA)
|
||||
{ "[Citygate D30 XT] Hedaka HED-919", "hed919", MACHINE_TYPE_286, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 1024, 64, 0, machine_xt_hed919_init, NULL },
|
||||
#endif
|
||||
|
||||
/* 286 AT machines */
|
||||
{ "[ISA] IBM AT", "ibmat", MACHINE_TYPE_286, {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibm_init, NULL },
|
||||
@@ -214,7 +216,7 @@ const machine_t machines[] = {
|
||||
{ "[ALi M1429G] Acer A1G", "acera1g", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO | MACHINE_PS2, 4, 36, 1, 127, machine_at_acera1g_init, at_acera1g_get_device },
|
||||
{ "[ALi M1429] Olystar LIL1429", "ali1429", MACHINE_TYPE_486, {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL },
|
||||
{ "[ALi M1429] AMI WinBIOS 486", "win486", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_winbios1429_init, NULL },
|
||||
{ "[VLSI 82C480] IBM PS/1 model 2133", "ibmps1_2133", MACHINE_TYPE_486, {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI | MACHINE_VIDEO, 1, 64, 1, 127, machine_ps1_m2133_init, ps1_m2133_get_device },
|
||||
{ "[VLSI 82C480] IBM PS/1 model 2133", "ibmps1_2133", MACHINE_TYPE_486, {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI | MACHINE_VIDEO, 2, 32, 1, 127, machine_ps1_m2133_init, ps1_m2133_get_device },
|
||||
|
||||
/* 486 machines with utilize the MCA bus */
|
||||
#if defined(DEV_BRANCH) && defined(USE_PS2M70T4)
|
||||
@@ -241,12 +243,10 @@ const machine_t machines[] = {
|
||||
|
||||
/* 430LX */
|
||||
{ "[i430LX] IBM Ambra DP60 PCI", "ambradp60", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp60_init, NULL },
|
||||
#if defined(DEV_BRANCH) && defined(USE_VPP60)
|
||||
{ "[i430LX] IBM PS/ValuePoint P60", "valuepointp60", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_valuepointp60_init, NULL },
|
||||
#endif
|
||||
{ "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_batman_init, NULL },
|
||||
#if defined(DEV_BRANCH) && defined(USE_DELLS4)
|
||||
{ "[i430LX] Dell OptiPlex 560L", "opti560l", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_opti560l_init, NULL },
|
||||
#if defined(DEV_BRANCH) && defined(USE_VPP60)
|
||||
{ "[i430LX] Dell Dimension XPS P60", "dellxp60", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_dellxp60_init, NULL },
|
||||
#endif
|
||||
{ "[i430LX] ASUS P/I-P5MP3", "p5mp3", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 192, 2, 127, machine_at_p5mp3_init, NULL },
|
||||
|
||||
@@ -122,6 +122,7 @@ int nic_do_log = ENABLE_NIC_LOG;
|
||||
static volatile int net_wait = 0;
|
||||
static mutex_t *network_mutex;
|
||||
static uint8_t *network_mac;
|
||||
static uint8_t network_timer_active = 0;
|
||||
static pc_timer_t network_rx_queue_timer;
|
||||
static netpkt_t *first_pkt[2] = { NULL, NULL },
|
||||
*last_pkt[2] = { NULL, NULL };
|
||||
@@ -354,6 +355,19 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKST
|
||||
timer_add(&network_rx_queue_timer, network_rx_queue, NULL, 0);
|
||||
/* 10 mbps. */
|
||||
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0);
|
||||
network_timer_active = 1;
|
||||
}
|
||||
|
||||
|
||||
/* Stop the network timer. */
|
||||
void
|
||||
network_timer_stop(void)
|
||||
{
|
||||
if (network_timer_active) {
|
||||
timer_stop(&network_rx_queue_timer);
|
||||
memset(&network_rx_queue_timer, 0x00, sizeof(pc_timer_t));
|
||||
network_timer_active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -361,7 +375,7 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKST
|
||||
void
|
||||
network_close(void)
|
||||
{
|
||||
timer_stop(&network_rx_queue_timer);
|
||||
network_timer_stop();
|
||||
|
||||
/* If already closed, do nothing. */
|
||||
if (network_mutex == NULL) return;
|
||||
|
||||
2
src/pc.c
2
src/pc.c
@@ -681,6 +681,8 @@ pc_reset_hard_close(void)
|
||||
{
|
||||
ui_sb_set_ready(0);
|
||||
|
||||
network_timer_stop();
|
||||
|
||||
/* Turn off timer processing to avoid potential segmentation faults. */
|
||||
timer_close();
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ serial_handler(i82091aa_t *dev, int uart)
|
||||
break;
|
||||
}
|
||||
|
||||
serial_setup(dev->uart[uart], uart_port, (dev->regs[0x20] & 0x10) ? 4 : 3);
|
||||
serial_setup(dev->uart[uart], uart_port, (dev->regs[reg] & 0x10) ? 4 : 3);
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +147,8 @@ i82091aa_write(uint16_t port, uint8_t val, void *priv)
|
||||
return;
|
||||
} else if (dev->cur_reg < 0x51)
|
||||
valxor = val ^ *reg;
|
||||
else if (dev->cur_reg >= 0x51)
|
||||
return;
|
||||
|
||||
switch(dev->cur_reg) {
|
||||
case 0x02:
|
||||
|
||||
@@ -39,18 +39,27 @@ ifeq ($(DEV_BUILD), y)
|
||||
ifndef AMD_K5
|
||||
AMD_K5 := y
|
||||
endif
|
||||
ifndef AMI386X
|
||||
AMI386SX := y
|
||||
endif
|
||||
ifndef CL5422
|
||||
CL5422 := y
|
||||
endif
|
||||
ifndef CYRIX_6X86
|
||||
CYRIX_6X86 := y
|
||||
CYRIX_6X86 := y
|
||||
endif
|
||||
ifndef HEADAKA
|
||||
HEDAKA := y
|
||||
endif
|
||||
ifndef LASERXT
|
||||
LASERXT := y
|
||||
endif
|
||||
ifndef MGA
|
||||
MGA := y
|
||||
endif
|
||||
ifndef OPEN_AT
|
||||
OPEN_AT := y
|
||||
endif
|
||||
ifndef PAS16
|
||||
PAS16 := n
|
||||
endif
|
||||
@@ -66,9 +75,6 @@ ifeq ($(DEV_BUILD), y)
|
||||
ifndef VECTRA54
|
||||
VECTRA54 := y
|
||||
endif
|
||||
ifndef VPP60
|
||||
VPP60 := y
|
||||
endif
|
||||
ifndef SIEMENS
|
||||
SIEMENS := y
|
||||
endif
|
||||
@@ -93,8 +99,8 @@ ifeq ($(DEV_BUILD), y)
|
||||
ifndef GUSMAX
|
||||
GUSMAX := y
|
||||
endif
|
||||
ifndef DELLXP60
|
||||
DELLXP60 := y
|
||||
ifndef DELLS4
|
||||
DELLS4 := y
|
||||
endif
|
||||
else
|
||||
ifndef DEBUG
|
||||
@@ -109,18 +115,27 @@ else
|
||||
ifndef AMD_K5
|
||||
AMD_K5 := n
|
||||
endif
|
||||
ifndef AMI386SX
|
||||
AMI386SX := n
|
||||
endif
|
||||
ifndef CL5422
|
||||
CL5422 := n
|
||||
endif
|
||||
ifndef CYRIX_6X86
|
||||
CYRIX_6X86 := n
|
||||
CYRIX_6X86 := n
|
||||
endif
|
||||
ifndef HEDAKA
|
||||
HEDAKA := n
|
||||
endif
|
||||
ifndef LASERXT
|
||||
LASERXT := n
|
||||
endif
|
||||
ifndef MGA
|
||||
MGA := n
|
||||
endif
|
||||
ifndef OPEN_AT
|
||||
OPEN_AT := n
|
||||
endif
|
||||
ifndef PAS16
|
||||
PAS16 := n
|
||||
endif
|
||||
@@ -136,9 +151,6 @@ else
|
||||
ifndef VECTRA54
|
||||
VECTRA54 := n
|
||||
endif
|
||||
ifndef VPP60
|
||||
VPP60 := n
|
||||
endif
|
||||
ifndef SIEMENS
|
||||
SIEMENS := n
|
||||
endif
|
||||
@@ -163,8 +175,8 @@ else
|
||||
ifndef GUSMAX
|
||||
GUSMAX := n
|
||||
endif
|
||||
ifndef DELLXP60
|
||||
DELLXP60 := n
|
||||
ifndef DELLS4
|
||||
DELLS4 := n
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -481,6 +493,10 @@ ifeq ($(AMD_K5), y)
|
||||
OPTS += -DUSE_AMD_K5
|
||||
endif
|
||||
|
||||
ifeq ($(AMI386SX), y)
|
||||
OPTS += -DUSE_AMI386SX
|
||||
endif
|
||||
|
||||
ifeq ($(CL5422), y)
|
||||
OPTS += -DUSE_CL5422
|
||||
endif
|
||||
@@ -489,6 +505,10 @@ ifeq ($(CYRIX_6X86), y)
|
||||
OPTS += -DUSE_CYRIX_6X86
|
||||
endif
|
||||
|
||||
ifeq ($(HEDAKA), y)
|
||||
OPTS += -DUSE_HEDAKA
|
||||
endif
|
||||
|
||||
ifeq ($(LASERXT), y)
|
||||
OPTS += -DUSE_LASERXT
|
||||
DEVBROBJ += m_xt_laserxt.o
|
||||
@@ -499,6 +519,10 @@ OPTS += -DUSE_MGA
|
||||
DEVBROBJ += vid_mga.o
|
||||
endif
|
||||
|
||||
ifeq ($(OPEN_AT), y)
|
||||
OPTS += -DUSE_OPEN_AT
|
||||
endif
|
||||
|
||||
ifeq ($(PAS16), y)
|
||||
OPTS += -DUSE_PAS16
|
||||
DEVBROBJ += snd_pas16.o
|
||||
@@ -520,10 +544,6 @@ ifeq ($(VECTRA54), y)
|
||||
OPTS += -DUSE_VECTRA54
|
||||
endif
|
||||
|
||||
ifeq ($(VPP60), y)
|
||||
OPTS += -DUSE_VPP60
|
||||
endif
|
||||
|
||||
ifeq ($(SIEMENS), y)
|
||||
OPTS += -DUSE_SIEMENS
|
||||
endif
|
||||
@@ -557,8 +577,8 @@ ifeq ($(GUSMAX), y)
|
||||
OPTS += -DUSE_GUSMAX
|
||||
endif
|
||||
|
||||
ifeq ($(DELLXP60), y)
|
||||
OPTS += -DUSE_DELLXP60
|
||||
ifeq ($(DELLS4), y)
|
||||
OPTS += -DUSE_DELLS4
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
Reference in New Issue
Block a user