Fix a setcr0 bug which was trashing the condition register; some system

calls are now implemented. A few tests more-or-less pass (but crash on
exit).
This commit is contained in:
David Given 2018-06-16 08:35:36 +02:00
parent 5111556d14
commit 5d7cdd2c67
2 changed files with 48 additions and 5 deletions

View file

@ -58,7 +58,7 @@ static bool getcr(uint8_t bit)
static void setcr(uint8_t bit, bool value)
{
bit = 31 - bit; /* note PowerPC bit numbering */
cpu.cr = cpu.cr & (1<<bit) | (value<<bit);
cpu.cr = cpu.cr & ~(1<<bit) | (value<<bit);
}
static void setcr0(bool setcr0, uint32_t value)
@ -227,9 +227,9 @@ void dump_state(FILE* stream)
{
int i;
fprintf(stream, "\n");
fprintf(stream, "pc=0x%08x lr=0x%08x ctr=0x%08x xer=0x%08x cr=0x%08x\n",
cpu.cia, cpu.lr, cpu.ctr, cpu.xer, cpu.cr);
fprintf(stream, "insn=0x%08x", read_long(cpu.cia));
for (i=0; i<32; i++)
{
if ((i % 4) == 0)
@ -237,6 +237,10 @@ void dump_state(FILE* stream)
fprintf(stream, "gpr%02d=0x%08x ", i, cpu.gpr[i]);
}
fprintf(stream, "\n");
/* This might fail and cause a reentrant trap if cia is invalid, so
* do it last. */
fprintf(stream, "insn=0x%08x", read_long(cpu.cia));
}
void single_step(void)

View file

@ -73,7 +73,11 @@ static uint32_t transform_address(uint32_t address)
uint32_t read_long(uint32_t address)
{
return READ_LONG(ram, transform_address(address));
uint32_t v = READ_LONG(ram, transform_address(address));
#if 0
fprintf(stderr, "read 0x%08x: 0x%08x\n", address, v);
#endif
return v;
}
@ -99,12 +103,45 @@ void write_word(uint32_t address, uint32_t value)
void write_long(uint32_t address, uint32_t value)
{
#if 0
fprintf(stderr, "write 0x%08x: 0x%08x\n", address, value);
#endif
WRITE_LONG(ram, transform_address(address), value);
}
void system_call(uint8_t trapno)
{
fatal("syscalls unimplemented");
cpu.cr &= ~(1<<28); /* reset summary overflow (for success) */
switch (cpu.gpr[0])
{
case 1: /* exit */
exit(cpu.gpr[3]);
case 4: /* write */
{
int fd = cpu.gpr[3];
uint32_t address = cpu.gpr[4];
uint32_t len = cpu.gpr[5];
void* ptr = ram + transform_address(address);
transform_address(address+len); /* bounds check */
cpu.gpr[4] = write(fd, ptr, len);
if (cpu.gpr[4] == -1)
goto error;
break;
}
case 126: /* sigprocmask */
cpu.gpr[4] = 0;
break;
error:
cpu.gpr[3] = errno;
cpu.cr |= (1<<28); /* set summary overflow (for failure) */
return;
default:
fatal("unimplemented system call %d", cpu.gpr[0]);
}
}
static void load_program(FILE* fd)
@ -177,7 +214,9 @@ int main(int argc, char* argv[])
for (;;)
{
//dump_state(stderr);
#if 0
dump_state(stderr);
#endif
single_step();
}