import recent kvm-unit-test changes (fixes incorrectly failing push es test)
This commit is contained in:
parent
fa0a75c927
commit
da0845189b
27
src/cpu.js
27
src/cpu.js
|
@ -1077,21 +1077,22 @@ CPU.prototype.load_multiboot = function(buffer)
|
|||
function() {});
|
||||
|
||||
// only for kvm-unit-test
|
||||
for(let i = 0xE; i <= 0xF; i++)
|
||||
for(let i = 0; i <= 0xF; i++)
|
||||
{
|
||||
this.io.register_write(0x2000 + i, this,
|
||||
function(value)
|
||||
function handle_write(value)
|
||||
{
|
||||
dbg_log("kvm-unit-test: Set irq " + h(i) + " to " + h(value, 2));
|
||||
if(value)
|
||||
{
|
||||
dbg_log("kvm-unit-test: Set irq " + h(i) + " to " + h(value, 2));
|
||||
if(value)
|
||||
{
|
||||
this.device_raise_irq(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.device_lower_irq(i);
|
||||
}
|
||||
});
|
||||
this.device_raise_irq(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.device_lower_irq(i);
|
||||
}
|
||||
}
|
||||
|
||||
this.io.register_write(0x2000 + i, this, handle_write, handle_write, handle_write);
|
||||
}
|
||||
|
||||
this.update_state_flags();
|
||||
|
|
|
@ -77,6 +77,15 @@ static void serial_init(void)
|
|||
lcr = inb(serial_iobase + 0x03);
|
||||
lcr &= ~0x80;
|
||||
outb(lcr, serial_iobase + 0x03);
|
||||
|
||||
/* IER: disable interrupts */
|
||||
outb(0x00, serial_iobase + 0x01);
|
||||
/* LCR: 8 bits, no parity, one stop bit */
|
||||
outb(0x03, serial_iobase + 0x03);
|
||||
/* FCR: disable FIFO queues */
|
||||
outb(0x00, serial_iobase + 0x02);
|
||||
/* MCR: RTS, DTR on */
|
||||
outb(0x03, serial_iobase + 0x04);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -115,6 +124,15 @@ static int failed;
|
|||
static void exit(int code)
|
||||
{
|
||||
outb(code, 0xf4);
|
||||
|
||||
if (code == 0)
|
||||
print_serial("--- DONE: 0 ---\n");
|
||||
else
|
||||
print_serial("--- DONE: 1 ---\n");
|
||||
|
||||
while (1) {
|
||||
asm volatile("hlt" ::: "memory");
|
||||
}
|
||||
}
|
||||
|
||||
struct regs {
|
||||
|
@ -234,7 +252,7 @@ static void exec_in_big_real_mode(struct insn_desc *insn)
|
|||
#define R_SP 64
|
||||
#define R_BP 128
|
||||
|
||||
int regs_equal(int ignore)
|
||||
static int regs_equal(int ignore)
|
||||
{
|
||||
const u32 *p1 = &inregs.eax, *p2 = &outregs.eax; // yuck
|
||||
int i;
|
||||
|
@ -271,7 +289,7 @@ static void report(const char *name, u16 regs_ignore, _Bool ok)
|
|||
); \
|
||||
extern struct insn_desc insn_##name;
|
||||
|
||||
void test_xchg(void)
|
||||
static void test_xchg(void)
|
||||
{
|
||||
MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
|
||||
MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
|
||||
|
@ -316,7 +334,7 @@ void test_xchg(void)
|
|||
outregs.eax == inregs.esp && outregs.esp == inregs.eax);
|
||||
}
|
||||
|
||||
void test_shld(void)
|
||||
static void test_shld(void)
|
||||
{
|
||||
MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
|
||||
|
||||
|
@ -326,7 +344,7 @@ void test_shld(void)
|
|||
report("shld", ~0, outregs.eax == 0xbeef);
|
||||
}
|
||||
|
||||
void test_mov_imm(void)
|
||||
static void test_mov_imm(void)
|
||||
{
|
||||
MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
|
||||
MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
|
||||
|
@ -354,7 +372,7 @@ void test_mov_imm(void)
|
|||
report("mov 5", R_AX, outregs.eax == 0x1234);
|
||||
}
|
||||
|
||||
void test_sub_imm(void)
|
||||
static void test_sub_imm(void)
|
||||
{
|
||||
MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
|
||||
MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
|
||||
|
@ -378,7 +396,7 @@ void test_sub_imm(void)
|
|||
report("sub 4", R_AX, outregs.eax == 0x24);
|
||||
}
|
||||
|
||||
void test_xor_imm(void)
|
||||
static void test_xor_imm(void)
|
||||
{
|
||||
MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
|
||||
MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
|
||||
|
@ -402,7 +420,7 @@ void test_xor_imm(void)
|
|||
report("xor 4", R_AX, outregs.eax == 0);
|
||||
}
|
||||
|
||||
void test_cmp_imm(void)
|
||||
static void test_cmp_imm(void)
|
||||
{
|
||||
MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
|
||||
"cmp $0x34, %al\n\t");
|
||||
|
@ -427,7 +445,7 @@ void test_cmp_imm(void)
|
|||
report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
|
||||
}
|
||||
|
||||
void test_add_imm(void)
|
||||
static void test_add_imm(void)
|
||||
{
|
||||
MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
|
||||
"add $0x12344321, %eax \n\t");
|
||||
|
@ -443,7 +461,7 @@ void test_add_imm(void)
|
|||
report("add 2", ~0, outregs.eax == 0x33);
|
||||
}
|
||||
|
||||
void test_eflags_insn(void)
|
||||
static void test_eflags_insn(void)
|
||||
{
|
||||
MK_INSN(clc, "clc");
|
||||
MK_INSN(stc, "stc");
|
||||
|
@ -473,7 +491,7 @@ void test_eflags_insn(void)
|
|||
report("std", ~0, (outregs.eflags & (1 << 10)));
|
||||
}
|
||||
|
||||
void test_io(void)
|
||||
static void test_io(void)
|
||||
{
|
||||
MK_INSN(io_test1, "mov $0xff, %al \n\t"
|
||||
"out %al, $0xe0 \n\t"
|
||||
|
@ -530,7 +548,7 @@ extern void retf(void);
|
|||
asm ("retf_imm: lretw $10");
|
||||
extern void retf_imm(void);
|
||||
|
||||
void test_call(void)
|
||||
static void test_call(void)
|
||||
{
|
||||
u32 addr;
|
||||
|
||||
|
@ -576,7 +594,7 @@ void test_call(void)
|
|||
report("retf imm 1", 0, 1);
|
||||
}
|
||||
|
||||
void test_jcc_short(void)
|
||||
static void test_jcc_short(void)
|
||||
{
|
||||
MK_INSN(jnz_short1, "jnz 1f\n\t"
|
||||
"mov $0x1234, %eax\n\t"
|
||||
|
@ -601,7 +619,7 @@ void test_jcc_short(void)
|
|||
report("jmp short 1", ~0, 1);
|
||||
}
|
||||
|
||||
void test_jcc_near(void)
|
||||
static void test_jcc_near(void)
|
||||
{
|
||||
/* encode near jmp manually. gas will not do it if offsets < 127 byte */
|
||||
MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
|
||||
|
@ -624,9 +642,9 @@ void test_jcc_near(void)
|
|||
report("jmp near 1", 0, 1);
|
||||
}
|
||||
|
||||
void test_long_jmp()
|
||||
static void test_long_jmp(void)
|
||||
{
|
||||
MK_INSN(long_jmp, "call 1f\n\t"
|
||||
MK_INSN(long_jmp, "calll 1f\n\t"
|
||||
"jmp 2f\n\t"
|
||||
"1: jmp $0, $test_function\n\t"
|
||||
"2:\n\t");
|
||||
|
@ -637,7 +655,7 @@ void test_long_jmp()
|
|||
report("jmp far 1", R_AX, outregs.eax == 0x1234);
|
||||
}
|
||||
|
||||
void test_push_pop()
|
||||
static void test_push_pop(void)
|
||||
{
|
||||
MK_INSN(push32, "mov $0x12345678, %eax\n\t"
|
||||
"push %eax\n\t"
|
||||
|
@ -649,24 +667,24 @@ void test_push_pop()
|
|||
MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
|
||||
"mov $0x123, %ax\n\t"
|
||||
"mov %ax, %es\n\t"
|
||||
"pushl %es\n\t"
|
||||
"pop %ebx \n\t"
|
||||
"pushw %es\n\t"
|
||||
"pop %bx \n\t"
|
||||
);
|
||||
MK_INSN(pop_es, "push %eax\n\t"
|
||||
"popl %es\n\t"
|
||||
MK_INSN(pop_es, "push %ax\n\t"
|
||||
"popw %es\n\t"
|
||||
"mov %es, %bx\n\t"
|
||||
);
|
||||
MK_INSN(push_pop_ss, "push %ss\n\t"
|
||||
MK_INSN(push_pop_ss, "pushw %ss\n\t"
|
||||
"pushw %ax\n\t"
|
||||
"popw %ss\n\t"
|
||||
"mov %ss, %bx\n\t"
|
||||
"pop %ss\n\t"
|
||||
"popw %ss\n\t"
|
||||
);
|
||||
MK_INSN(push_pop_fs, "push %fs\n\t"
|
||||
MK_INSN(push_pop_fs, "pushl %fs\n\t"
|
||||
"pushl %eax\n\t"
|
||||
"popl %fs\n\t"
|
||||
"mov %fs, %ebx\n\t"
|
||||
"pop %fs\n\t"
|
||||
"popl %fs\n\t"
|
||||
);
|
||||
MK_INSN(push_pop_high_esp_bits,
|
||||
"xor $0x12340000, %esp \n\t"
|
||||
|
@ -703,7 +721,7 @@ void test_push_pop()
|
|||
report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
|
||||
}
|
||||
|
||||
void test_null(void)
|
||||
static void test_null(void)
|
||||
{
|
||||
MK_INSN(null, "");
|
||||
|
||||
|
@ -715,26 +733,26 @@ void test_null(void)
|
|||
|
||||
static void test_pusha_popa(void)
|
||||
{
|
||||
MK_INSN(pusha, "pusha\n\t"
|
||||
"pop %edi\n\t"
|
||||
"pop %esi\n\t"
|
||||
"pop %ebp\n\t"
|
||||
"add $4, %esp\n\t"
|
||||
"pop %ebx\n\t"
|
||||
"pop %edx\n\t"
|
||||
"pop %ecx\n\t"
|
||||
"pop %eax\n\t"
|
||||
MK_INSN(pusha, "pushal\n\t"
|
||||
"popl %edi\n\t"
|
||||
"popl %esi\n\t"
|
||||
"popl %ebp\n\t"
|
||||
"addl $4, %esp\n\t"
|
||||
"popl %ebx\n\t"
|
||||
"popl %edx\n\t"
|
||||
"popl %ecx\n\t"
|
||||
"popl %eax\n\t"
|
||||
);
|
||||
|
||||
MK_INSN(popa, "push %eax\n\t"
|
||||
"push %ecx\n\t"
|
||||
"push %edx\n\t"
|
||||
"push %ebx\n\t"
|
||||
"push %esp\n\t"
|
||||
"push %ebp\n\t"
|
||||
"push %esi\n\t"
|
||||
"push %edi\n\t"
|
||||
"popa\n\t"
|
||||
MK_INSN(popa, "pushl %eax\n\t"
|
||||
"pushl %ecx\n\t"
|
||||
"pushl %edx\n\t"
|
||||
"pushl %ebx\n\t"
|
||||
"pushl %esp\n\t"
|
||||
"pushl %ebp\n\t"
|
||||
"pushl %esi\n\t"
|
||||
"pushl %edi\n\t"
|
||||
"popal\n\t"
|
||||
);
|
||||
|
||||
init_inregs(&(struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6 });
|
||||
|
@ -746,11 +764,11 @@ static void test_pusha_popa(void)
|
|||
report("pusha/popa 1", 0, 1);
|
||||
}
|
||||
|
||||
void test_iret()
|
||||
static void test_iret(void)
|
||||
{
|
||||
MK_INSN(iret32, "pushf\n\t"
|
||||
MK_INSN(iret32, "pushfl\n\t"
|
||||
"pushl %cs\n\t"
|
||||
"call 1f\n\t" /* a near call will push eip onto the stack */
|
||||
"calll 1f\n\t" /* a near call will push eip onto the stack */
|
||||
"jmp 2f\n\t"
|
||||
"1: iretl\n\t"
|
||||
"2:\n\t"
|
||||
|
@ -769,7 +787,7 @@ void test_iret()
|
|||
"orl $0xffc18028, %eax\n\t"
|
||||
"pushl %eax\n\t"
|
||||
"pushl %cs\n\t"
|
||||
"call 1f\n\t"
|
||||
"calll 1f\n\t"
|
||||
"jmp 2f\n\t"
|
||||
"1: iretl\n\t"
|
||||
"2:\n\t");
|
||||
|
@ -801,7 +819,7 @@ void test_iret()
|
|||
report("iret 4", R_AX, 1);
|
||||
}
|
||||
|
||||
void test_int()
|
||||
static void test_int(void)
|
||||
{
|
||||
init_inregs(NULL);
|
||||
|
||||
|
@ -814,7 +832,27 @@ void test_int()
|
|||
report("int 1", 0, 1);
|
||||
}
|
||||
|
||||
void test_imul()
|
||||
static void test_sti_inhibit(void)
|
||||
{
|
||||
init_inregs(NULL);
|
||||
|
||||
*(u32 *)(0x73 * 4) = 0x1000; /* Store IRQ 11 handler in the IDT */
|
||||
*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
|
||||
|
||||
MK_INSN(sti_inhibit, "cli\n\t"
|
||||
"movw $0x200b, %dx\n\t"
|
||||
"movl $1, %eax\n\t"
|
||||
"outl %eax, %dx\n\t" /* Set IRQ11 */
|
||||
"movl $0, %eax\n\t"
|
||||
"outl %eax, %dx\n\t" /* Clear IRQ11 */
|
||||
"sti\n\t"
|
||||
"hlt\n\t");
|
||||
exec_in_big_real_mode(&insn_sti_inhibit);
|
||||
|
||||
report("sti inhibit", ~0, 1);
|
||||
}
|
||||
|
||||
static void test_imul(void)
|
||||
{
|
||||
MK_INSN(imul8_1, "mov $2, %al\n\t"
|
||||
"mov $-4, %cx\n\t"
|
||||
|
@ -863,7 +901,7 @@ void test_imul()
|
|||
report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
|
||||
}
|
||||
|
||||
void test_mul()
|
||||
static void test_mul(void)
|
||||
{
|
||||
MK_INSN(mul8, "mov $2, %al\n\t"
|
||||
"mov $4, %cx\n\t"
|
||||
|
@ -889,7 +927,7 @@ void test_mul()
|
|||
report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
|
||||
}
|
||||
|
||||
void test_div()
|
||||
static void test_div(void)
|
||||
{
|
||||
MK_INSN(div8, "mov $257, %ax\n\t"
|
||||
"mov $2, %cl\n\t"
|
||||
|
@ -917,7 +955,7 @@ void test_div()
|
|||
outregs.eax == 102 && outregs.edx == 2);
|
||||
}
|
||||
|
||||
void test_idiv()
|
||||
static void test_idiv(void)
|
||||
{
|
||||
MK_INSN(idiv8, "mov $256, %ax\n\t"
|
||||
"mov $-2, %cl\n\t"
|
||||
|
@ -943,7 +981,7 @@ void test_idiv()
|
|||
report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
|
||||
}
|
||||
|
||||
void test_cbw(void)
|
||||
static void test_cbw(void)
|
||||
{
|
||||
MK_INSN(cbw, "mov $0xFE, %eax \n\t"
|
||||
"cbw\n\t");
|
||||
|
@ -959,7 +997,7 @@ void test_cbw(void)
|
|||
report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
|
||||
}
|
||||
|
||||
void test_loopcc(void)
|
||||
static void test_loopcc(void)
|
||||
{
|
||||
MK_INSN(loop, "mov $10, %ecx\n\t"
|
||||
"1: inc %eax\n\t"
|
||||
|
@ -1271,7 +1309,7 @@ static void test_das(void)
|
|||
report("DAS", ~0, nr_fail == 0);
|
||||
}
|
||||
|
||||
void test_cwd_cdq()
|
||||
static void test_cwd_cdq(void)
|
||||
{
|
||||
/* Sign-bit set */
|
||||
MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
|
||||
|
@ -1316,14 +1354,14 @@ static struct {
|
|||
0x10,
|
||||
};
|
||||
|
||||
void test_lds_lss()
|
||||
static void test_lds_lss(void)
|
||||
{
|
||||
init_inregs(&(struct regs){ .ebx = (unsigned long)&desc });
|
||||
|
||||
MK_INSN(lds, "push %ds\n\t"
|
||||
MK_INSN(lds, "pushl %ds\n\t"
|
||||
"lds (%ebx), %eax\n\t"
|
||||
"mov %ds, %ebx\n\t"
|
||||
"pop %ds\n\t");
|
||||
"popl %ds\n\t");
|
||||
exec_in_big_real_mode(&insn_lds);
|
||||
report("lds", R_AX | R_BX,
|
||||
outregs.eax == (unsigned long)desc.address &&
|
||||
|
@ -1336,35 +1374,35 @@ void test_lds_lss()
|
|||
outregs.eax == (unsigned long)desc.address &&
|
||||
outregs.ebx == desc.sel);
|
||||
|
||||
MK_INSN(lfs, "push %fs\n\t"
|
||||
MK_INSN(lfs, "pushl %fs\n\t"
|
||||
"lfs (%ebx), %eax\n\t"
|
||||
"mov %fs, %ebx\n\t"
|
||||
"pop %fs\n\t");
|
||||
"popl %fs\n\t");
|
||||
exec_in_big_real_mode(&insn_lfs);
|
||||
report("lfs", R_AX | R_BX,
|
||||
outregs.eax == (unsigned long)desc.address &&
|
||||
outregs.ebx == desc.sel);
|
||||
|
||||
MK_INSN(lgs, "push %gs\n\t"
|
||||
MK_INSN(lgs, "pushl %gs\n\t"
|
||||
"lgs (%ebx), %eax\n\t"
|
||||
"mov %gs, %ebx\n\t"
|
||||
"pop %gs\n\t");
|
||||
"popl %gs\n\t");
|
||||
exec_in_big_real_mode(&insn_lgs);
|
||||
report("lgs", R_AX | R_BX,
|
||||
outregs.eax == (unsigned long)desc.address &&
|
||||
outregs.ebx == desc.sel);
|
||||
|
||||
MK_INSN(lss, "push %ss\n\t"
|
||||
MK_INSN(lss, "mov %ss, %dx\n\t"
|
||||
"lss (%ebx), %eax\n\t"
|
||||
"mov %ss, %ebx\n\t"
|
||||
"pop %ss\n\t");
|
||||
"mov %dx, %ss\n\t");
|
||||
exec_in_big_real_mode(&insn_lss);
|
||||
report("lss", R_AX | R_BX,
|
||||
outregs.eax == (unsigned long)desc.address &&
|
||||
outregs.ebx == desc.sel);
|
||||
}
|
||||
|
||||
void test_jcxz(void)
|
||||
static void test_jcxz(void)
|
||||
{
|
||||
MK_INSN(jcxz1, "jcxz 1f\n\t"
|
||||
"mov $0x1234, %eax\n\t"
|
||||
|
@ -1700,7 +1738,7 @@ static void test_perf_memory_adc(void)
|
|||
print_serial(" millicycles/emulated ADC instruction\n");
|
||||
}
|
||||
|
||||
void test_dr_mod(void)
|
||||
static void test_dr_mod(void)
|
||||
{
|
||||
MK_INSN(drmod, "movl %ebx, %dr0\n\t"
|
||||
".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t");
|
||||
|
@ -1711,7 +1749,7 @@ void test_dr_mod(void)
|
|||
report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced);
|
||||
}
|
||||
|
||||
void test_smsw(void)
|
||||
static void test_smsw(void)
|
||||
{
|
||||
MK_INSN(smsw, "movl %cr0, %ebx\n\t"
|
||||
"movl %ebx, %ecx\n\t"
|
||||
|
@ -1726,7 +1764,7 @@ void test_smsw(void)
|
|||
report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
|
||||
}
|
||||
|
||||
void test_xadd(void)
|
||||
static void test_xadd(void)
|
||||
{
|
||||
MK_INSN(xadd, "xaddl %eax, %eax\n\t");
|
||||
|
||||
|
@ -1739,6 +1777,10 @@ void test_xadd(void)
|
|||
|
||||
void realmode_start(void)
|
||||
{
|
||||
// enable interrupts (v86 only)
|
||||
outb(0, 0x21);
|
||||
outb(0, 0xa1);
|
||||
|
||||
test_null();
|
||||
|
||||
test_shld();
|
||||
|
@ -1760,6 +1802,7 @@ void realmode_start(void)
|
|||
test_xchg();
|
||||
test_iret();
|
||||
test_int();
|
||||
test_sti_inhibit();
|
||||
test_imul();
|
||||
test_mul();
|
||||
test_div();
|
||||
|
@ -1801,6 +1844,7 @@ void realmode_start(void)
|
|||
unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
|
||||
|
||||
struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
|
||||
struct table_descr r_idt_descr = { 0x3ff, 0 };
|
||||
|
||||
asm(
|
||||
".section .init \n\t"
|
||||
|
@ -1821,6 +1865,7 @@ asm(
|
|||
".text \n\t"
|
||||
"start: \n\t"
|
||||
"lgdt r_gdt_descr \n\t"
|
||||
"lidt r_idt_descr \n\t"
|
||||
"ljmp $8, $1f; 1: \n\t"
|
||||
".code16gcc \n\t"
|
||||
"mov $16, %eax \n\t"
|
||||
|
|
Loading…
Reference in a new issue