提交 a541f297 编写于 作者: B bellard

PowerPC system emulation fixes (Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@722 c046a42c-6fe2-441c-8c8c-71466251a162
上级 df475d18
...@@ -16,8 +16,12 @@ DYNGEN=../dyngen$(EXESUF) ...@@ -16,8 +16,12 @@ DYNGEN=../dyngen$(EXESUF)
QEMU_USER=qemu-$(TARGET_ARCH) QEMU_USER=qemu-$(TARGET_ARCH)
# system emulator name # system emulator name
ifdef CONFIG_SOFTMMU ifdef CONFIG_SOFTMMU
ifeq ($(TARGET_ARCH), i386)
QEMU_SYSTEM=qemu$(EXESUF) QEMU_SYSTEM=qemu$(EXESUF)
else else
QEMU_SYSTEM=qemu-system-$(TARGET_ARCH)$(EXESUF)
endif
else
QEMU_SYSTEM=qemu-fast QEMU_SYSTEM=qemu-fast
endif endif
...@@ -222,14 +226,23 @@ ifeq ($(ARCH),alpha) ...@@ -222,14 +226,23 @@ ifeq ($(ARCH),alpha)
endif endif
# must use static linking to avoid leaving stuff in virtual address space # must use static linking to avoid leaving stuff in virtual address space
VL_OBJS=vl.o osdep.o block.o monitor.o \ VL_OBJS=vl.o osdep.o block.o monitor.o
ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o \
fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o ifeq ($(TARGET_ARCH), i386)
ifdef CONFIG_GDBSTUB # Hardware support
VL_OBJS+=gdbstub.o VL_OBJS+= ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
endif endif
ifeq ($(TARGET_ARCH), ppc) ifeq ($(TARGET_ARCH), ppc)
VL_OBJS+= hw.o # Generic PPC support
VL_OBJS+= ppc.o
# PREP hardware support
VL_OBJS+= ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o ppc_prep.o
#VL_OBJS+= hw.o of.o setup.o
endif
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
endif endif
ifdef CONFIG_SDL ifdef CONFIG_SDL
VL_OBJS+=sdl.o VL_OBJS+=sdl.o
......
...@@ -27,7 +27,7 @@ ar="ar" ...@@ -27,7 +27,7 @@ ar="ar"
make="make" make="make"
strip="strip" strip="strip"
cpu=`uname -m` cpu=`uname -m`
target_list="i386-user i386 i386-softmmu arm-user sparc-user ppc-user" target_list="i386-user i386 i386-softmmu arm-user sparc-user ppc-user ppc-softmmu"
case "$cpu" in case "$cpu" in
i386|i486|i586|i686|i86pc|BePC) i386|i486|i586|i686|i86pc|BePC)
cpu="i386" cpu="i386"
......
...@@ -190,7 +190,7 @@ int cpu_exec(CPUState *env1) ...@@ -190,7 +190,7 @@ int cpu_exec(CPUState *env1)
(env->eflags & IF_MASK) && (env->eflags & IF_MASK) &&
!(env->hflags & HF_INHIBIT_IRQ_MASK)) { !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno; int intno;
intno = cpu_x86_get_pic_interrupt(env); intno = cpu_get_pic_interrupt(env);
if (loglevel & CPU_LOG_TB_IN_ASM) { if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
} }
......
...@@ -578,7 +578,13 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) ...@@ -578,7 +578,13 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
#endif #endif
if (__builtin_expect(env->tlb_read[is_user][index].address != if (__builtin_expect(env->tlb_read[is_user][index].address !=
(addr & TARGET_PAGE_MASK), 0)) { (addr & TARGET_PAGE_MASK), 0)) {
#if defined (TARGET_PPC)
env->access_type = ACCESS_CODE;
ldub_code((void *)addr); ldub_code((void *)addr);
env->access_type = ACCESS_INT;
#else
ldub_code((void *)addr);
#endif
} }
return addr + env->tlb_read[is_user][index].addend - (unsigned long)phys_ram_base; return addr + env->tlb_read[is_user][index].addend - (unsigned long)phys_ram_base;
} }
......
...@@ -914,7 +914,7 @@ static void tb_reset_jump_recursive(TranslationBlock *tb) ...@@ -914,7 +914,7 @@ static void tb_reset_jump_recursive(TranslationBlock *tb)
breakpoint is reached */ breakpoint is reached */
int cpu_breakpoint_insert(CPUState *env, uint32_t pc) int cpu_breakpoint_insert(CPUState *env, uint32_t pc)
{ {
#if defined(TARGET_I386) #if defined(TARGET_I386) || defined(TARGET_PPC)
int i; int i;
for(i = 0; i < env->nb_breakpoints; i++) { for(i = 0; i < env->nb_breakpoints; i++) {
...@@ -935,7 +935,7 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc) ...@@ -935,7 +935,7 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc)
/* remove a breakpoint */ /* remove a breakpoint */
int cpu_breakpoint_remove(CPUState *env, uint32_t pc) int cpu_breakpoint_remove(CPUState *env, uint32_t pc)
{ {
#if defined(TARGET_I386) #if defined(TARGET_I386) || defined(TARGET_PPC)
int i; int i;
for(i = 0; i < env->nb_breakpoints; i++) { for(i = 0; i < env->nb_breakpoints; i++) {
if (env->breakpoints[i] == pc) if (env->breakpoints[i] == pc)
...@@ -957,7 +957,7 @@ int cpu_breakpoint_remove(CPUState *env, uint32_t pc) ...@@ -957,7 +957,7 @@ int cpu_breakpoint_remove(CPUState *env, uint32_t pc)
CPU loop after each instruction */ CPU loop after each instruction */
void cpu_single_step(CPUState *env, int enabled) void cpu_single_step(CPUState *env, int enabled)
{ {
#if defined(TARGET_I386) #if defined(TARGET_I386) || defined(TARGET_PPC)
if (env->singlestep_enabled != enabled) { if (env->singlestep_enabled != enabled) {
env->singlestep_enabled = enabled; env->singlestep_enabled = enabled;
/* must flush all the translated code to avoid inconsistancies */ /* must flush all the translated code to avoid inconsistancies */
......
...@@ -220,42 +220,49 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) ...@@ -220,42 +220,49 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
} }
#elif defined (TARGET_PPC) #elif defined (TARGET_PPC)
static void to_le32(uint8_t *p, int v) static void to_le32(uint32_t *buf, uint32_t v)
{ {
uint8_t *p = (uint8_t *)buf;
p[3] = v; p[3] = v;
p[2] = v >> 8; p[2] = v >> 8;
p[1] = v >> 16; p[1] = v >> 16;
p[0] = v >> 24; p[0] = v >> 24;
} }
static uint32_t from_le32 (uint32_t *buf)
{
uint8_t *p = (uint8_t *)buf;
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{ {
uint32_t tmp; uint32_t *registers = (uint32_t *)mem_buf, tmp;
int i; int i;
/* fill in gprs */ /* fill in gprs */
for(i = 0; i < 8; i++) { for(i = 0; i < 32; i++) {
to_le32(mem_buf + i * 4, env->gpr[i]); to_le32(&registers[i], env->gpr[i]);
} }
/* fill in fprs */ /* fill in fprs */
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
to_le32(mem_buf + (i * 2) + 32, *((uint32_t *)&env->fpr[i])); to_le32(&registers[(i * 2) + 32], *((uint32_t *)&env->fpr[i]));
to_le32(mem_buf + (i * 2) + 33, *((uint32_t *)&env->fpr[i] + 1)); to_le32(&registers[(i * 2) + 33], *((uint32_t *)&env->fpr[i] + 1));
} }
/* nip, msr, ccr, lnk, ctr, xer, mq */ /* nip, msr, ccr, lnk, ctr, xer, mq */
to_le32(mem_buf + 96, tswapl(env->nip)); to_le32(&registers[96], (uint32_t)env->nip/* - 4*/);
to_le32(mem_buf + 97, tswapl(_load_msr())); to_le32(&registers[97], _load_msr(env));
to_le32(mem_buf + 98, 0);
tmp = 0; tmp = 0;
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
tmp |= env->crf[i] << (32 - (i * 4)); tmp |= env->crf[i] << (32 - ((i + 1) * 4));
to_le32(mem_buf + 98, tmp); to_le32(&registers[98], tmp);
to_le32(mem_buf + 99, tswapl(env->lr)); to_le32(&registers[99], env->lr);
to_le32(mem_buf + 100, tswapl(env->ctr)); to_le32(&registers[100], env->ctr);
to_le32(mem_buf + 101, tswapl(_load_xer())); to_le32(&registers[101], _load_xer(env));
to_le32(mem_buf + 102, 0); to_le32(&registers[102], 0);
return 102; return 103 * 4;
} }
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
...@@ -265,22 +272,22 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) ...@@ -265,22 +272,22 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
/* fill in gprs */ /* fill in gprs */
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
env->gpr[i] = tswapl(registers[i]); env->gpr[i] = from_le32(&registers[i]);
} }
/* fill in fprs */ /* fill in fprs */
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
*((uint32_t *)&env->fpr[i]) = tswapl(registers[(i * 2) + 32]); *((uint32_t *)&env->fpr[i]) = from_le32(&registers[(i * 2) + 32]);
*((uint32_t *)&env->fpr[i] + 1) = tswapl(registers[(i * 2) + 33]); *((uint32_t *)&env->fpr[i] + 1) = from_le32(&registers[(i * 2) + 33]);
} }
/* nip, msr, ccr, lnk, ctr, xer, mq */ /* nip, msr, ccr, lnk, ctr, xer, mq */
env->nip = tswapl(registers[96]); env->nip = from_le32(&registers[96]);
_store_msr(tswapl(registers[97])); _store_msr(env, from_le32(&registers[97]));
registers[98] = tswapl(registers[98]); registers[98] = from_le32(&registers[98]);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
env->crf[i] = (registers[98] >> (32 - (i * 4))) & 0xF; env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF;
env->lr = tswapl(registers[99]); env->lr = from_le32(&registers[99]);
env->ctr = tswapl(registers[100]); env->ctr = from_le32(&registers[100]);
_store_xer(tswapl(registers[101])); _store_xer(env, from_le32(&registers[101]));
} }
#else #else
......
...@@ -83,7 +83,6 @@ typedef struct fdrive_t { ...@@ -83,7 +83,6 @@ typedef struct fdrive_t {
uint8_t dir; /* Direction */ uint8_t dir; /* Direction */
uint8_t rw; /* Read/write */ uint8_t rw; /* Read/write */
/* Media */ /* Media */
fdisk_type_t disk; /* Disk type */
fdisk_flags_t flags; fdisk_flags_t flags;
uint8_t last_sect; /* Nb sector per track */ uint8_t last_sect; /* Nb sector per track */
uint8_t max_track; /* Nb of tracks */ uint8_t max_track; /* Nb of tracks */
...@@ -102,7 +101,6 @@ static void fd_init (fdrive_t *drv, BlockDriverState *bs) ...@@ -102,7 +101,6 @@ static void fd_init (fdrive_t *drv, BlockDriverState *bs)
drv->drflags = 0; drv->drflags = 0;
drv->perpendicular = 0; drv->perpendicular = 0;
/* Disk */ /* Disk */
drv->disk = FDRIVE_DISK_NONE;
drv->last_sect = 0; drv->last_sect = 0;
drv->max_track = 0; drv->max_track = 0;
} }
...@@ -171,26 +169,113 @@ static void fd_recalibrate (fdrive_t *drv) ...@@ -171,26 +169,113 @@ static void fd_recalibrate (fdrive_t *drv)
drv->rw = 0; drv->rw = 0;
} }
/* Recognize floppy formats */
typedef struct fd_format_t {
fdrive_type_t drive;
fdisk_type_t disk;
uint8_t last_sect;
uint8_t max_track;
uint8_t max_head;
const unsigned char *str;
} fd_format_t;
static fd_format_t fd_formats[] = {
/* First entry is default format */
/* 1.44 MB 3"1/2 floppy disks */
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 18, 80, 1, "1.44 MB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 20, 80, 1, "1.6 MB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 80, 1, "1.68 MB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 82, 1, "1.72 MB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 83, 1, "1.74 MB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 22, 80, 1, "1.76 MB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 23, 80, 1, "1.84 MB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 24, 80, 1, "1.92 MB 3\"1/2", },
/* 2.88 MB 3"1/2 floppy disks */
{ FDRIVE_DRV_288, FDRIVE_DISK_288, 36, 80, 1, "2.88 MB 3\"1/2", },
{ FDRIVE_DRV_288, FDRIVE_DISK_288, 39, 80, 1, "3.12 MB 3\"1/2", },
{ FDRIVE_DRV_288, FDRIVE_DISK_288, 40, 80, 1, "3.2 MB 3\"1/2", },
{ FDRIVE_DRV_288, FDRIVE_DISK_288, 44, 80, 1, "3.52 MB 3\"1/2", },
{ FDRIVE_DRV_288, FDRIVE_DISK_288, 48, 80, 1, "3.84 MB 3\"1/2", },
/* 720 kB 3"1/2 floppy disks */
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 1, "720 kB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 80, 1, "800 kB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 82, 1, "820 kB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 83, 1, "830 kB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 13, 80, 1, "1.04 MB 3\"1/2", },
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 14, 80, 1, "1.12 MB 3\"1/2", },
/* 1.2 MB 5"1/4 floppy disks */
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 15, 80, 1, "1.2 kB 5\"1/4", },
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 80, 1, "1.44 MB 5\"1/4", },
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 82, 1, "1.48 MB 5\"1/4", },
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 83, 1, "1.49 MB 5\"1/4", },
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 20, 80, 1, "1.6 MB 5\"1/4", },
/* 720 kB 5"1/4 floppy disks */
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 80, 1, "720 kB 5\"1/4", },
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 11, 80, 1, "880 kB 5\"1/4", },
/* 360 kB 5"1/4 floppy disks */
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 1, "360 kB 5\"1/4", },
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 0, "180 kB 5\"1/4", },
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 41, 1, "410 kB 5\"1/4", },
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 42, 1, "420 kB 5\"1/4", },
/* 320 kB 5"1/4 floppy disks */
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 1, "320 kB 5\"1/4", },
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 0, "160 kB 5\"1/4", },
/* 360 kB must match 5"1/4 better than 3"1/2... */
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 0, "360 kB 3\"1/2", },
/* end */
{ FDRIVE_DRV_NONE, FDRIVE_DISK_NONE, -1, -1, 0, NULL, },
};
/* Revalidate a disk drive after a disk change */ /* Revalidate a disk drive after a disk change */
static void fd_revalidate (fdrive_t *drv) static void fd_revalidate (fdrive_t *drv)
{ {
int64_t nb_sectors; fd_format_t *parse;
int64_t nb_sectors, size;
int i, first_match, match;
int nb_heads, max_track, last_sect, ro; int nb_heads, max_track, last_sect, ro;
FLOPPY_DPRINTF("revalidate\n"); FLOPPY_DPRINTF("revalidate\n");
drv->drflags &= ~FDRIVE_REVALIDATE; drv->drflags &= ~FDRIVE_REVALIDATE;
if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
/* if no drive present, cannot do more */
if (!drv->bs)
return;
if (bdrv_is_inserted(drv->bs)) {
ro = bdrv_is_read_only(drv->bs); ro = bdrv_is_read_only(drv->bs);
bdrv_get_geometry_hint(drv->bs, &max_track, &nb_heads, &last_sect); bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
if (nb_heads != 0 && max_track != 0 && last_sect != 0) { if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
drv->disk = FDRIVE_DISK_USER;
printf("User defined disk (%d %d %d)", printf("User defined disk (%d %d %d)",
nb_heads - 1, max_track, last_sect); nb_heads - 1, max_track, last_sect);
} else {
bdrv_get_geometry(drv->bs, &nb_sectors);
match = -1;
first_match = -1;
for (i = 0;; i++) {
parse = &fd_formats[i];
if (parse->drive == FDRIVE_DRV_NONE)
break;
if (drv->drive == parse->drive ||
drv->drive == FDRIVE_DRV_NONE) {
size = (parse->max_head + 1) * parse->max_track *
parse->last_sect;
if (nb_sectors == size) {
match = i;
break;
}
if (first_match == -1)
first_match = i;
}
}
if (match == -1) {
if (first_match == -1)
match = 1;
else
match = first_match;
parse = &fd_formats[match];
}
nb_heads = parse->max_head + 1;
max_track = parse->max_track;
last_sect = parse->last_sect;
drv->drive = parse->drive;
printf("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
nb_heads, max_track, last_sect, ro ? "ro" : "rw");
}
if (nb_heads == 1) { if (nb_heads == 1) {
drv->flags &= ~FDISK_DBL_SIDES; drv->flags &= ~FDISK_DBL_SIDES;
} else { } else {
...@@ -198,236 +283,9 @@ static void fd_revalidate (fdrive_t *drv) ...@@ -198,236 +283,9 @@ static void fd_revalidate (fdrive_t *drv)
} }
drv->max_track = max_track; drv->max_track = max_track;
drv->last_sect = last_sect; drv->last_sect = last_sect;
} else {
bdrv_get_geometry(drv->bs, &nb_sectors);
switch (nb_sectors) {
/* 2.88 MB 3"1/2 drive disks */
case 7680:
printf("3.84 Mb 3\"1/2 disk (1 80 48)");
drv->drive = FDRIVE_DRV_288;
drv->disk = FDRIVE_DISK_288;
drv->last_sect = 48;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 7040:
printf("3.52 Mb 3\"1/2 disk (1 80 44)");
drv->drive = FDRIVE_DRV_288;
drv->disk = FDRIVE_DISK_288;
drv->last_sect = 44;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 6400:
printf("3.2 Mb 3\"1/2 disk (1 80 40)");
drv->drive = FDRIVE_DRV_288;
drv->disk = FDRIVE_DISK_288;
drv->last_sect = 40;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 6240:
printf("3.12 Mb 3\"1/2 disk (1 80 39)");
drv->drive = FDRIVE_DRV_288;
drv->disk = FDRIVE_DISK_288;
drv->last_sect = 39;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 5760:
printf("2.88 Mb 3\"1/2 disk (1 80 36)");
drv->drive = FDRIVE_DRV_288;
drv->disk = FDRIVE_DISK_288;
drv->last_sect = 36;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
/* 1.44 MB 3"1/2 drive disks */
case 3840:
printf("1.92 Mb 3\"1/2 disk (1 80 24)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_144;
drv->last_sect = 24;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 3680:
printf("1.84 Mb 3\"1/2 disk (1 80 23)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_144;
drv->last_sect = 23;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 3520:
printf("1.76 Mb 3\"1/2 disk (1 80 22)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_144;
drv->last_sect = 22;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 3486:
printf("1.74 Mb 3\"1/2 disk (1 83 21)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_144;
drv->last_sect = 21;
drv->max_track = 83;
drv->flags |= FDISK_DBL_SIDES;
break;
case 3444:
printf("1.72 Mb 3\"1/2 disk (1 82 21)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_144;
drv->last_sect = 21;
drv->max_track = 82;
drv->flags |= FDISK_DBL_SIDES;
break;
case 3360:
printf("1.68 Mb 3\"1/2 disk (1 80 21)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_144;
drv->last_sect = 21;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 3200:
printf("1.6 Mb 3\"1/2 disk (1 80 20)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_144;
drv->last_sect = 20;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 2880:
default:
printf("1.44 Mb 3\"1/2 disk (1 80 18)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_144;
drv->last_sect = 18;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
/* 720 kB 3"1/2 drive disks */
case 2240:
printf("1.12 Mb 3\"1/2 disk (1 80 14)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_720;
drv->last_sect = 14;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 2080:
printf("1.04 Mb 3\"1/2 disk (1 80 13)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_720;
drv->last_sect = 13;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 1660:
printf("830 kb 3\"1/2 disk (1 83 10)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_720;
drv->last_sect = 10;
drv->max_track = 83;
drv->flags |= FDISK_DBL_SIDES;
break;
case 1640:
printf("820 kb 3\"1/2 disk (1 82 10)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_720;
drv->last_sect = 10;
drv->max_track = 82;
drv->flags |= FDISK_DBL_SIDES;
break;
case 1600:
printf("800 kb 3\"1/2 disk (1 80 10)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_720;
drv->last_sect = 10;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 1440:
printf("720 kb 3\"1/2 disk (1 80 9)");
drv->drive = FDRIVE_DRV_144;
drv->disk = FDRIVE_DISK_720;
drv->last_sect = 9;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
/* 1.2 MB 5"1/4 drive disks */
case 2988:
printf("1.49 Mb 5\"1/4 disk (1 83 18)");
drv->drive = FDRIVE_DRV_120;
drv->disk = FDRIVE_DISK_144; /* ? */
drv->last_sect = 18;
drv->max_track = 83;
drv->flags |= FDISK_DBL_SIDES;
break;
case 2952:
printf("1.48 Mb 5\"1/4 disk (1 82 18)");
drv->drive = FDRIVE_DRV_120;
drv->disk = FDRIVE_DISK_144; /* ? */
drv->last_sect = 18;
drv->max_track = 82;
drv->flags |= FDISK_DBL_SIDES;
break;
case 2400:
printf("1.2 Mb 5\"1/4 disk (1 80 15)");
drv->drive = FDRIVE_DRV_120;
drv->disk = FDRIVE_DISK_144; /* ? */
drv->last_sect = 15;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
case 1760:
printf("880 kb 5\"1/4 disk (1 80 11)");
drv->drive = FDRIVE_DRV_120;
drv->disk = FDRIVE_DISK_144; /* ? */
drv->last_sect = 11;
drv->max_track = 80;
drv->flags |= FDISK_DBL_SIDES;
break;
/* 360 kB 5"1/4 drive disks */
case 840:
/* 420 kB 5"1/4 disk */
printf("420 kb 5\"1/4 disk (1 42 10)");
drv->drive = FDRIVE_DRV_120;
drv->disk = FDRIVE_DISK_144; /* ? */
drv->last_sect = 10;
drv->max_track = 42;
drv->flags |= FDISK_DBL_SIDES;
case 820:
/* 410 kB 5"1/4 disk */
printf("410 kb 5\"1/4 disk (1 41 10)");
drv->drive = FDRIVE_DRV_120;
drv->disk = FDRIVE_DISK_144; /* ? */
drv->last_sect = 10;
drv->max_track = 41;
drv->flags |= FDISK_DBL_SIDES;
case 720:
/* 360 kB 5"1/4 disk */
printf("360 kb 5\"1/4 disk (1 40 9)");
drv->drive = FDRIVE_DRV_120;
drv->disk = FDRIVE_DISK_144; /* ? */
drv->last_sect = 9;
drv->max_track = 40;
drv->flags |= FDISK_DBL_SIDES;
break;
}
printf(" %s\n", ro == 0 ? "rw" : "ro");
}
drv->ro = ro; drv->ro = ro;
} else { } else {
printf("No disk in drive\n"); printf("No disk in drive\n");
drv->disk = FDRIVE_DISK_NONE;
drv->last_sect = 0; drv->last_sect = 0;
drv->max_track = 0; drv->max_track = 0;
drv->flags &= ~FDISK_DBL_SIDES; drv->flags &= ~FDISK_DBL_SIDES;
...@@ -544,20 +402,29 @@ static uint32_t fdctrl_read (void *opaque, uint32_t reg) ...@@ -544,20 +402,29 @@ static uint32_t fdctrl_read (void *opaque, uint32_t reg)
fdctrl_t *fdctrl = opaque; fdctrl_t *fdctrl = opaque;
uint32_t retval; uint32_t retval;
if (reg == fdctrl->io_base + 0x01) switch (reg & 0x07) {
case 0x01:
retval = fdctrl_read_statusB(fdctrl); retval = fdctrl_read_statusB(fdctrl);
else if (reg == fdctrl->io_base + 0x02) break;
case 0x02:
retval = fdctrl_read_dor(fdctrl); retval = fdctrl_read_dor(fdctrl);
else if (reg == fdctrl->io_base + 0x03) break;
case 0x03:
retval = fdctrl_read_tape(fdctrl); retval = fdctrl_read_tape(fdctrl);
else if (reg == fdctrl->io_base + 0x04) break;
case 0x04:
retval = fdctrl_read_main_status(fdctrl); retval = fdctrl_read_main_status(fdctrl);
else if (reg == fdctrl->io_base + 0x05) break;
case 0x05:
retval = fdctrl_read_data(fdctrl); retval = fdctrl_read_data(fdctrl);
else if (reg == fdctrl->io_base + 0x07) break;
case 0x07:
retval = fdctrl_read_dir(fdctrl); retval = fdctrl_read_dir(fdctrl);
else break;
default:
retval = (uint32_t)(-1); retval = (uint32_t)(-1);
break;
}
return retval; return retval;
} }
...@@ -566,14 +433,22 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value) ...@@ -566,14 +433,22 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
{ {
fdctrl_t *fdctrl = opaque; fdctrl_t *fdctrl = opaque;
if (reg == fdctrl->io_base + 0x02) switch (reg & 0x07) {
case 0x02:
fdctrl_write_dor(fdctrl, value); fdctrl_write_dor(fdctrl, value);
else if (reg == fdctrl->io_base + 0x03) break;
case 0x03:
fdctrl_write_tape(fdctrl, value); fdctrl_write_tape(fdctrl, value);
else if (reg == fdctrl->io_base + 0x04) break;
case 0x04:
fdctrl_write_rate(fdctrl, value); fdctrl_write_rate(fdctrl, value);
else if (reg == fdctrl->io_base + 0x05) break;
case 0x05:
fdctrl_write_data(fdctrl, value); fdctrl_write_data(fdctrl, value);
break;
default:
break;
}
} }
static void fd_change_cb (void *opaque) static void fd_change_cb (void *opaque)
...@@ -581,7 +456,6 @@ static void fd_change_cb (void *opaque) ...@@ -581,7 +456,6 @@ static void fd_change_cb (void *opaque)
fdrive_t *drv = opaque; fdrive_t *drv = opaque;
FLOPPY_DPRINTF("disk change\n"); FLOPPY_DPRINTF("disk change\n");
/* TODO: use command-line parameters to force geometry */
fd_revalidate(drv); fd_revalidate(drv);
#if 0 #if 0
fd_recalibrate(drv); fd_recalibrate(drv);
...@@ -606,7 +480,7 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, ...@@ -606,7 +480,7 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
fdctrl->irq_lvl = irq_lvl; fdctrl->irq_lvl = irq_lvl;
fdctrl->dma_chann = dma_chann; fdctrl->dma_chann = dma_chann;
fdctrl->io_base = io_base; fdctrl->io_base = io_base;
fdctrl->config = 0x40; /* Implicit seek, polling & FIFO enabled */ fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
if (fdctrl->dma_chann != -1) { if (fdctrl->dma_chann != -1) {
fdctrl->dma_en = 1; fdctrl->dma_en = 1;
DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl); DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
...@@ -634,9 +508,10 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, ...@@ -634,9 +508,10 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl); register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl);
register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl); register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl);
} }
for (i = 0; i < MAX_FD; i++) { for (i = 0; i < 2; i++) {
fd_revalidate(&fdctrl->drives[i]); fd_revalidate(&fdctrl->drives[i]);
} }
return fdctrl; return fdctrl;
} }
......
...@@ -174,7 +174,7 @@ static inline void pic_intack(PicState *s, int irq) ...@@ -174,7 +174,7 @@ static inline void pic_intack(PicState *s, int irq)
s->irr &= ~(1 << irq); s->irr &= ~(1 << irq);
} }
int cpu_x86_get_pic_interrupt(CPUState *env) int cpu_get_pic_interrupt(CPUState *env)
{ {
int irq, irq2, intno; int irq, irq2, intno;
......
/*
* QEMU M48T59 NVRAM emulation for PPC PREP platform
*
* Copyright (c) 2003-2004 Jocelyn Mayer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h> /* needed by vl.h */
#include <stdint.h>
#include <string.h>
#include <time.h>
#include "vl.h"
//#define NVRAM_DEBUG
#if defined(NVRAM_DEBUG)
#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
#else
#define NVRAM_PRINTF(fmt, args...) do { } while (0)
#endif
typedef struct m48t59_t {
/* Hardware parameters */
int IRQ;
uint32_t io_base;
uint16_t size;
/* RTC management */
time_t time_offset;
time_t stop_time;
/* Alarm & watchdog */
time_t alarm;
struct QEMUTimer *alrm_timer;
struct QEMUTimer *wd_timer;
/* NVRAM storage */
uint16_t addr;
uint8_t *buffer;
} m48t59_t;
static m48t59_t *NVRAMs;
static int nb_NVRAMs;
/* Fake timer functions */
/* Generic helpers for BCD */
static inline uint8_t toBCD (uint8_t value)
{
return (((value / 10) % 10) << 4) | (value % 10);
}
static inline uint8_t fromBCD (uint8_t BCD)
{
return ((BCD >> 4) * 10) + (BCD & 0x0F);
}
/* RTC management helpers */
static void get_time (m48t59_t *NVRAM, struct tm *tm)
{
time_t t;
t = time(NULL) + NVRAM->time_offset;
localtime_r(&t, tm);
}
static void set_time (m48t59_t *NVRAM, struct tm *tm)
{
time_t now, new_time;
new_time = mktime(tm);
now = time(NULL);
NVRAM->time_offset = new_time - now;
}
/* Alarm management */
static void alarm_cb (void *opaque)
{
struct tm tm, tm_now;
uint64_t next_time;
m48t59_t *NVRAM = opaque;
pic_set_irq(NVRAM->IRQ, 1);
if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a month */
get_time(NVRAM, &tm_now);
memcpy(&tm, &tm_now, sizeof(struct tm));
tm.tm_mon++;
if (tm.tm_mon == 13) {
tm.tm_mon = 1;
tm.tm_year++;
}
next_time = mktime(&tm);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a day */
next_time = 24 * 60 * 60 + mktime(&tm_now);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once an hour */
next_time = 60 * 60 + mktime(&tm_now);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a minute */
next_time = 60 + mktime(&tm_now);
} else {
/* Repeat once a second */
next_time = 1 + mktime(&tm_now);
}
qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
pic_set_irq(NVRAM->IRQ, 0);
}
static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
{
localtime_r(&NVRAM->alarm, tm);
}
static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
{
NVRAM->alarm = mktime(tm);
if (NVRAM->alrm_timer != NULL) {
qemu_del_timer(NVRAM->alrm_timer);
NVRAM->alrm_timer = NULL;
}
if (NVRAM->alarm - time(NULL) > 0)
qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
}
/* Watchdog management */
static void watchdog_cb (void *opaque)
{
m48t59_t *NVRAM = opaque;
NVRAM->buffer[0x1FF0] |= 0x80;
if (NVRAM->buffer[0x1FF7] & 0x80) {
NVRAM->buffer[0x1FF7] = 0x00;
NVRAM->buffer[0x1FFC] &= ~0x40;
// reset_CPU();
} else {
pic_set_irq(NVRAM->IRQ, 1);
pic_set_irq(NVRAM->IRQ, 0);
}
}
static void set_up_watchdog (m48t59_t *NVRAM, uint8_t value)
{
uint64_t interval; /* in 1/16 seconds */
if (NVRAM->wd_timer != NULL) {
qemu_del_timer(NVRAM->wd_timer);
NVRAM->wd_timer = NULL;
}
NVRAM->buffer[0x1FF0] &= ~0x80;
if (value != 0) {
interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
((interval * 1000) >> 4));
}
}
/* Direct access to NVRAM */
void m48t59_write (void *opaque, uint32_t val)
{
m48t59_t *NVRAM = opaque;
struct tm tm;
int tmp;
if (NVRAM->addr > 0x1FF8 && NVRAM->addr < 0x2000)
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
switch (NVRAM->addr) {
case 0x1FF0:
/* flags register : read-only */
break;
case 0x1FF1:
/* unused */
break;
case 0x1FF2:
/* alarm seconds */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_alarm(NVRAM, &tm);
tm.tm_sec = tmp;
NVRAM->buffer[0x1FF2] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF3:
/* alarm minutes */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_alarm(NVRAM, &tm);
tm.tm_min = tmp;
NVRAM->buffer[0x1FF3] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF4:
/* alarm hours */
tmp = fromBCD(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
get_alarm(NVRAM, &tm);
tm.tm_hour = tmp;
NVRAM->buffer[0x1FF4] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF5:
/* alarm date */
tmp = fromBCD(val & 0x1F);
if (tmp != 0) {
get_alarm(NVRAM, &tm);
tm.tm_mday = tmp;
NVRAM->buffer[0x1FF5] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF6:
/* interrupts */
NVRAM->buffer[0x1FF6] = val;
break;
case 0x1FF7:
/* watchdog */
NVRAM->buffer[0x1FF7] = val;
set_up_watchdog(NVRAM, val);
break;
case 0x1FF8:
/* control */
NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
break;
case 0x1FF9:
/* seconds (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_sec = tmp;
set_time(NVRAM, &tm);
}
if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
if (val & 0x80) {
NVRAM->stop_time = time(NULL);
} else {
NVRAM->time_offset += NVRAM->stop_time - time(NULL);
NVRAM->stop_time = 0;
}
}
NVRAM->buffer[0x1FF9] = val & 0x80;
break;
case 0x1FFA:
/* minutes (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_min = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFB:
/* hours (BCD) */
tmp = fromBCD(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
get_time(NVRAM, &tm);
tm.tm_hour = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFC:
/* day of the week / century */
tmp = fromBCD(val & 0x07);
get_time(NVRAM, &tm);
tm.tm_wday = tmp;
set_time(NVRAM, &tm);
NVRAM->buffer[0x1FFC] = val & 0x40;
break;
case 0x1FFD:
/* date */
tmp = fromBCD(val & 0x1F);
if (tmp != 0) {
get_time(NVRAM, &tm);
tm.tm_mday = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFE:
/* month */
tmp = fromBCD(val & 0x1F);
if (tmp >= 1 && tmp <= 12) {
get_time(NVRAM, &tm);
tm.tm_mon = tmp - 1;
set_time(NVRAM, &tm);
}
break;
case 0x1FFF:
/* year */
tmp = fromBCD(val);
if (tmp >= 0 && tmp <= 99) {
get_time(NVRAM, &tm);
tm.tm_year = fromBCD(val);
set_time(NVRAM, &tm);
}
break;
default:
if (NVRAM->addr < 0x1FF0 ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
NVRAM->buffer[NVRAM->addr] = val & 0xFF;
}
break;
}
}
uint32_t m48t59_read (void *opaque)
{
m48t59_t *NVRAM = opaque;
struct tm tm;
uint32_t retval = 0xFF;
switch (NVRAM->addr) {
case 0x1FF0:
/* flags register */
goto do_read;
case 0x1FF1:
/* unused */
retval = 0;
break;
case 0x1FF2:
/* alarm seconds */
goto do_read;
case 0x1FF3:
/* alarm minutes */
goto do_read;
case 0x1FF4:
/* alarm hours */
goto do_read;
case 0x1FF5:
/* alarm date */
goto do_read;
case 0x1FF6:
/* interrupts */
goto do_read;
case 0x1FF7:
/* A read resets the watchdog */
set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
goto do_read;
case 0x1FF8:
/* control */
goto do_read;
case 0x1FF9:
/* seconds (BCD) */
get_time(NVRAM, &tm);
retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
break;
case 0x1FFA:
/* minutes (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_min);
break;
case 0x1FFB:
/* hours (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_hour);
break;
case 0x1FFC:
/* day of the week / century */
get_time(NVRAM, &tm);
retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
break;
case 0x1FFD:
/* date */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mday);
break;
case 0x1FFE:
/* month */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mon + 1);
break;
case 0x1FFF:
/* year */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_year);
break;
default:
if (NVRAM->addr < 0x1FF0 ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
do_read:
retval = NVRAM->buffer[NVRAM->addr];
}
break;
}
if (NVRAM->addr > 0x1FF9 && NVRAM->addr < 0x2000)
NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval);
return retval;
}
void m48t59_set_addr (void *opaque, uint32_t addr)
{
m48t59_t *NVRAM = opaque;
NVRAM->addr = addr;
}
/* IO access to NVRAM */
static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->io_base;
switch (addr) {
case 0:
NVRAM->addr &= ~0x00FF;
NVRAM->addr |= val;
break;
case 1:
NVRAM->addr &= ~0xFF00;
NVRAM->addr |= val << 8;
break;
case 3:
m48t59_write(NVRAM, val);
NVRAM->addr = 0x0000;
break;
default:
break;
}
}
static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
{
m48t59_t *NVRAM = opaque;
if (addr == NVRAM->io_base + 3)
return m48t59_read(NVRAM);
return 0xFF;
}
/* Initialisation routine */
void *m48t59_init (int IRQ, uint32_t io_base, uint16_t size)
{
m48t59_t *tmp;
tmp = realloc(NVRAMs, (nb_NVRAMs + 1) * sizeof(m48t59_t));
if (tmp == NULL)
return NULL;
NVRAMs = tmp;
tmp[nb_NVRAMs].buffer = malloc(size);
if (tmp[nb_NVRAMs].buffer == NULL)
return NULL;
memset(tmp[nb_NVRAMs].buffer, 0, size);
tmp[nb_NVRAMs].IRQ = IRQ;
tmp[nb_NVRAMs].size = size;
tmp[nb_NVRAMs].io_base = io_base;
tmp[nb_NVRAMs].addr = 0;
register_ioport_read(io_base, 0x04, 1, NVRAM_readb, &NVRAMs[nb_NVRAMs]);
register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, &NVRAMs[nb_NVRAMs]);
tmp[nb_NVRAMs].alrm_timer = qemu_new_timer(vm_clock, &alarm_cb,
&tmp[nb_NVRAMs]);
tmp[nb_NVRAMs].wd_timer = qemu_new_timer(vm_clock, &watchdog_cb,
&tmp[nb_NVRAMs]);
return &NVRAMs[nb_NVRAMs++];
}
#if !defined (__M48T59_H__)
#define __M48T59_H__
void m48t59_write (void *opaque, uint32_t val);
uint32_t m48t59_read (void *opaque);
void m48t59_set_addr (void *opaque, uint32_t addr);
void *m48t59_init (int IRQ, uint32_t io_base, uint16_t size);
#endif /* !defined (__M48T59_H__) */
...@@ -146,6 +146,10 @@ static void ne2000_update_irq(NE2000State *s) ...@@ -146,6 +146,10 @@ static void ne2000_update_irq(NE2000State *s)
{ {
int isr; int isr;
isr = s->isr & s->imr; isr = s->isr & s->imr;
#if defined(DEBUG_NE2000)
printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
s->irq, isr ? 1 : 0, s->isr, s->imr);
#endif
if (isr) if (isr)
pic_set_irq(s->irq, 1); pic_set_irq(s->irq, 1);
else else
......
/*
* QEMU generic PPC hardware System Emulator
*
* Copyright (c) 2003-2004 Jocelyn Mayer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include "vl.h"
void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename);
void ppc_init (int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
/* For now, only PREP is supported */
return ppc_prep_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
snapshot, kernel_filename, kernel_cmdline,
initrd_filename);
}
此差异已折叠。
...@@ -94,15 +94,15 @@ int cpu_inl(CPUState *env, int addr) ...@@ -94,15 +94,15 @@ int cpu_inl(CPUState *env, int addr)
return 0; return 0;
} }
#ifdef TARGET_I386 int cpu_get_pic_interrupt(CPUState *env)
/***********************************************************/
/* CPUX86 core interface */
int cpu_x86_get_pic_interrupt(CPUState *env)
{ {
return -1; return -1;
} }
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
static void write_dt(void *ptr, unsigned long addr, unsigned long limit, static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
int flags) int flags)
{ {
...@@ -441,7 +441,6 @@ void cpu_loop (CPUSPARCState *env) ...@@ -441,7 +441,6 @@ void cpu_loop (CPUSPARCState *env)
#endif #endif
#ifdef TARGET_PPC #ifdef TARGET_PPC
void cpu_loop(CPUPPCState *env) void cpu_loop(CPUPPCState *env)
{ {
target_siginfo_t info; target_siginfo_t info;
...@@ -769,6 +768,8 @@ void cpu_loop(CPUPPCState *env) ...@@ -769,6 +768,8 @@ void cpu_loop(CPUPPCState *env)
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* Don't know why this should ever happen... */ /* Don't know why this should ever happen... */
break; break;
case EXCP_DEBUG:
break;
default: default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr); trapnr);
......
...@@ -2475,6 +2475,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ...@@ -2475,6 +2475,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
} }
#endif #endif
break; break;
#ifdef TARGET_NR_getdents64
case TARGET_NR_getdents64: case TARGET_NR_getdents64:
{ {
struct dirent64 *dirp = (void *)arg2; struct dirent64 *dirp = (void *)arg2;
...@@ -2498,6 +2499,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ...@@ -2498,6 +2499,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
} }
} }
break; break;
#endif /* TARGET_NR_getdents64 */
case TARGET_NR__newselect: case TARGET_NR__newselect:
ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4, ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4,
(void *)arg5); (void *)arg5);
......
...@@ -530,6 +530,47 @@ typedef struct MonitorDef { ...@@ -530,6 +530,47 @@ typedef struct MonitorDef {
int (*get_value)(struct MonitorDef *md); int (*get_value)(struct MonitorDef *md);
} MonitorDef; } MonitorDef;
#if defined(TARGET_PPC)
static int monitor_get_ccr (struct MonitorDef *md)
{
unsigned int u;
int i;
u = 0;
for (i = 0; i < 8; i++)
u |= cpu_single_env->crf[i] << (32 - (4 * i));
return u;
}
static int monitor_get_msr (struct MonitorDef *md)
{
return (cpu_single_env->msr[MSR_POW] << MSR_POW) |
(cpu_single_env->msr[MSR_ILE] << MSR_ILE) |
(cpu_single_env->msr[MSR_EE] << MSR_EE) |
(cpu_single_env->msr[MSR_PR] << MSR_PR) |
(cpu_single_env->msr[MSR_FP] << MSR_FP) |
(cpu_single_env->msr[MSR_ME] << MSR_ME) |
(cpu_single_env->msr[MSR_FE0] << MSR_FE0) |
(cpu_single_env->msr[MSR_SE] << MSR_SE) |
(cpu_single_env->msr[MSR_BE] << MSR_BE) |
(cpu_single_env->msr[MSR_FE1] << MSR_FE1) |
(cpu_single_env->msr[MSR_IP] << MSR_IP) |
(cpu_single_env->msr[MSR_IR] << MSR_IR) |
(cpu_single_env->msr[MSR_DR] << MSR_DR) |
(cpu_single_env->msr[MSR_RI] << MSR_RI) |
(cpu_single_env->msr[MSR_LE] << MSR_LE);
}
static int monitor_get_xer (struct MonitorDef *md)
{
return (cpu_single_env->xer[XER_SO] << XER_SO) |
(cpu_single_env->xer[XER_OV] << XER_OV) |
(cpu_single_env->xer[XER_CA] << XER_CA) |
(cpu_single_env->xer[XER_BC] << XER_BC);
}
#endif
static MonitorDef monitor_defs[] = { static MonitorDef monitor_defs[] = {
#ifdef TARGET_I386 #ifdef TARGET_I386
{ "eax", offsetof(CPUState, regs[0]) }, { "eax", offsetof(CPUState, regs[0]) },
...@@ -542,6 +583,65 @@ static MonitorDef monitor_defs[] = { ...@@ -542,6 +583,65 @@ static MonitorDef monitor_defs[] = {
{ "esi", offsetof(CPUState, regs[7]) }, { "esi", offsetof(CPUState, regs[7]) },
{ "eflags", offsetof(CPUState, eflags) }, { "eflags", offsetof(CPUState, eflags) },
{ "eip|pc", offsetof(CPUState, eip) }, { "eip|pc", offsetof(CPUState, eip) },
#elif defined(TARGET_PPC)
{ "r0", offsetof(CPUState, gpr[0]) },
{ "r1", offsetof(CPUState, gpr[1]) },
{ "r2", offsetof(CPUState, gpr[2]) },
{ "r3", offsetof(CPUState, gpr[3]) },
{ "r4", offsetof(CPUState, gpr[4]) },
{ "r5", offsetof(CPUState, gpr[5]) },
{ "r6", offsetof(CPUState, gpr[6]) },
{ "r7", offsetof(CPUState, gpr[7]) },
{ "r8", offsetof(CPUState, gpr[8]) },
{ "r9", offsetof(CPUState, gpr[9]) },
{ "r10", offsetof(CPUState, gpr[10]) },
{ "r11", offsetof(CPUState, gpr[11]) },
{ "r12", offsetof(CPUState, gpr[12]) },
{ "r13", offsetof(CPUState, gpr[13]) },
{ "r14", offsetof(CPUState, gpr[14]) },
{ "r15", offsetof(CPUState, gpr[15]) },
{ "r16", offsetof(CPUState, gpr[16]) },
{ "r17", offsetof(CPUState, gpr[17]) },
{ "r18", offsetof(CPUState, gpr[18]) },
{ "r19", offsetof(CPUState, gpr[19]) },
{ "r20", offsetof(CPUState, gpr[20]) },
{ "r21", offsetof(CPUState, gpr[21]) },
{ "r22", offsetof(CPUState, gpr[22]) },
{ "r23", offsetof(CPUState, gpr[23]) },
{ "r24", offsetof(CPUState, gpr[24]) },
{ "r25", offsetof(CPUState, gpr[25]) },
{ "r26", offsetof(CPUState, gpr[26]) },
{ "r27", offsetof(CPUState, gpr[27]) },
{ "r28", offsetof(CPUState, gpr[28]) },
{ "r29", offsetof(CPUState, gpr[29]) },
{ "r30", offsetof(CPUState, gpr[30]) },
{ "r31", offsetof(CPUState, gpr[31]) },
{ "lr", offsetof(CPUState, lr) },
{ "ctr", offsetof(CPUState, ctr) },
{ "decr", offsetof(CPUState, decr) },
{ "ccr", 0, &monitor_get_ccr, },
{ "msr", 0, &monitor_get_msr, },
{ "xer", 0, &monitor_get_xer, },
{ "tbu", offsetof(CPUState, tb[0]) },
{ "tbl", offsetof(CPUState, tb[1]) },
{ "sdr1", offsetof(CPUState, sdr1) },
{ "sr0", offsetof(CPUState, sr[0]) },
{ "sr1", offsetof(CPUState, sr[1]) },
{ "sr2", offsetof(CPUState, sr[2]) },
{ "sr3", offsetof(CPUState, sr[3]) },
{ "sr4", offsetof(CPUState, sr[4]) },
{ "sr5", offsetof(CPUState, sr[5]) },
{ "sr6", offsetof(CPUState, sr[6]) },
{ "sr7", offsetof(CPUState, sr[7]) },
{ "sr8", offsetof(CPUState, sr[8]) },
{ "sr9", offsetof(CPUState, sr[9]) },
{ "sr10", offsetof(CPUState, sr[10]) },
{ "sr11", offsetof(CPUState, sr[11]) },
{ "sr12", offsetof(CPUState, sr[12]) },
{ "sr13", offsetof(CPUState, sr[13]) },
{ "sr14", offsetof(CPUState, sr[14]) },
{ "sr15", offsetof(CPUState, sr[15]) },
/* Too lazy to put BATs and SPRs ... */
#endif #endif
{ NULL }, { NULL },
}; };
......
...@@ -20,9 +20,6 @@ ...@@ -20,9 +20,6 @@
#if !defined (__CPU_PPC_H__) #if !defined (__CPU_PPC_H__)
#define __CPU_PPC_H__ #define __CPU_PPC_H__
#include <endian.h>
#include <asm/byteorder.h>
#define TARGET_LONG_BITS 32 #define TARGET_LONG_BITS 32
#include "cpu-defs.h" #include "cpu-defs.h"
...@@ -157,14 +154,26 @@ typedef struct CPUPPCState { ...@@ -157,14 +154,26 @@ typedef struct CPUPPCState {
int error_code; int error_code;
int access_type; /* when a memory exception occurs, the access int access_type; /* when a memory exception occurs, the access
type is stored here */ type is stored here */
#if 0 /* TODO */
uint32_t pending_exceptions; /* For external & decr exception,
* that can be delayed */
#else
uint32_t exceptions; /* exception queue */ uint32_t exceptions; /* exception queue */
uint32_t errors[16]; uint32_t errors[32];
#endif
int user_mode_only; /* user mode only simulation */ int user_mode_only; /* user mode only simulation */
struct TranslationBlock *current_tb; /* currently executing TB */ struct TranslationBlock *current_tb; /* currently executing TB */
/* soft mmu support */ /* soft mmu support */
/* 0 = kernel, 1 = user */ /* 0 = kernel, 1 = user (may have 2 = kernel code, 3 = user code ?) */
CPUTLBEntry tlb_read[2][CPU_TLB_SIZE]; CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
CPUTLBEntry tlb_write[2][CPU_TLB_SIZE]; CPUTLBEntry tlb_write[2][CPU_TLB_SIZE];
/* ice debug support */
uint32_t breakpoints[MAX_BREAKPOINTS];
int nb_breakpoints;
int brkstate;
int singlestep_enabled;
/* user data */ /* user data */
void *opaque; void *opaque;
} CPUPPCState; } CPUPPCState;
...@@ -179,14 +188,21 @@ struct siginfo; ...@@ -179,14 +188,21 @@ struct siginfo;
int cpu_ppc_signal_handler(int host_signum, struct siginfo *info, int cpu_ppc_signal_handler(int host_signum, struct siginfo *info,
void *puc); void *puc);
void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags); void do_interrupt (CPUPPCState *env);
void cpu_loop_exit(void); void cpu_loop_exit(void);
void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags);
void dump_stack (CPUPPCState *env); void dump_stack (CPUPPCState *env);
uint32_t _load_xer (void);
void _store_xer (uint32_t value); uint32_t _load_xer (CPUPPCState *env);
uint32_t _load_msr (void); void _store_xer (CPUPPCState *env, uint32_t value);
void _store_msr (uint32_t value); uint32_t _load_msr (CPUPPCState *env);
void do_interrupt (CPUPPCState *env); void _store_msr (CPUPPCState *env, uint32_t value);
void PPC_init_hw (uint32_t mem_size,
uint32_t kernel_addr, uint32_t kernel_size,
uint32_t stack_addr, int boot_device,
const unsigned char *initrd_file);
#define TARGET_PAGE_BITS 12 #define TARGET_PAGE_BITS 12
#include "cpu-all.h" #include "cpu-all.h"
...@@ -277,14 +293,6 @@ void do_interrupt (CPUPPCState *env); ...@@ -277,14 +293,6 @@ void do_interrupt (CPUPPCState *env);
#define TARGET_PAGE_BITS 12 #define TARGET_PAGE_BITS 12
#include "cpu-all.h" #include "cpu-all.h"
CPUPPCState *cpu_ppc_init(void);
int cpu_ppc_exec(CPUPPCState *s);
void cpu_ppc_close(CPUPPCState *s);
void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags);
void PPC_init_hw (CPUPPCState *env, uint32_t mem_size,
uint32_t kernel_addr, uint32_t kernel_size,
uint32_t stack_addr, int boot_device);
/* Memory access type : /* Memory access type :
* may be needed for precise access rights control and precise exceptions. * may be needed for precise access rights control and precise exceptions.
*/ */
...@@ -351,12 +359,14 @@ enum { ...@@ -351,12 +359,14 @@ enum {
/* flags for EXCP_DSI */ /* flags for EXCP_DSI */
EXCP_DSI_DIRECT = 0x10, EXCP_DSI_DIRECT = 0x10,
EXCP_DSI_STORE = 0x20, EXCP_DSI_STORE = 0x20,
EXCP_ECXW = 0x40, EXCP_DSI_ECXW = 0x40,
/* Exception subtypes for EXCP_ISI */ /* Exception subtypes for EXCP_ISI */
EXCP_ISI_TRANSLATE = 0x01, /* Code address can't be translated */ EXCP_ISI_TRANSLATE = 0x01, /* Code address can't be translated */
EXCP_ISI_NOEXEC = 0x02, /* Try to fetch from a data segment */ EXCP_ISI_NOEXEC = 0x02, /* Try to fetch from a data segment */
EXCP_ISI_GUARD = 0x03, /* Fetch from guarded memory */ EXCP_ISI_GUARD = 0x03, /* Fetch from guarded memory */
EXCP_ISI_PROT = 0x04, /* Memory protection violation */ EXCP_ISI_PROT = 0x04, /* Memory protection violation */
EXCP_ISI_DIRECT = 0x05, /* Trying to fetch from *
* a direct store segment */
/* Exception subtypes for EXCP_ALIGN */ /* Exception subtypes for EXCP_ALIGN */
EXCP_ALIGN_FP = 0x01, /* FP alignment exception */ EXCP_ALIGN_FP = 0x01, /* FP alignment exception */
EXCP_ALIGN_LST = 0x02, /* Unaligned mult/extern load/store */ EXCP_ALIGN_LST = 0x02, /* Unaligned mult/extern load/store */
......
...@@ -36,7 +36,11 @@ register uint32_t T2 asm(AREG3); ...@@ -36,7 +36,11 @@ register uint32_t T2 asm(AREG3);
#define FTS1 ((float)env->ft1) #define FTS1 ((float)env->ft1)
#define FTS2 ((float)env->ft2) #define FTS2 ((float)env->ft2)
#if defined (DEBUG_OP)
#define RETURN() __asm__ __volatile__("nop");
#else
#define RETURN() __asm__ __volatile__(""); #define RETURN() __asm__ __volatile__("");
#endif
#include "cpu.h" #include "cpu.h"
#include "exec-all.h" #include "exec-all.h"
...@@ -149,6 +153,7 @@ void do_icbi (void); ...@@ -149,6 +153,7 @@ void do_icbi (void);
void do_tlbia (void); void do_tlbia (void);
void do_tlbie (void); void do_tlbie (void);
void dump_state (void);
void dump_rfi (void); void dump_rfi (void);
void dump_store_sr (int srnum); void dump_store_sr (int srnum);
void dump_store_ibat (int ul, int nr); void dump_store_ibat (int ul, int nr);
......
此差异已折叠。
...@@ -18,11 +18,11 @@ ...@@ -18,11 +18,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
//#define DEBUG_OP
#include "config.h" #include "config.h"
#include "exec.h" #include "exec.h"
//#define DEBUG_OP
#define regs (env) #define regs (env)
#define Ts0 (int32_t)T0 #define Ts0 (int32_t)T0
#define Ts1 (int32_t)T1 #define Ts1 (int32_t)T1
...@@ -226,6 +226,17 @@ PPC_OP(process_exceptions) ...@@ -226,6 +226,17 @@ PPC_OP(process_exceptions)
} }
} }
PPC_OP(debug)
{
env->nip = PARAM(1);
env->brkstate = 1;
#if defined (DEBUG_OP)
dump_state();
#endif
do_queue_exception(EXCP_DEBUG);
RETURN();
}
/* Segment registers load and store with immediate index */ /* Segment registers load and store with immediate index */
PPC_OP(load_srin) PPC_OP(load_srin)
{ {
...@@ -1443,10 +1454,9 @@ PPC_OP(fneg) ...@@ -1443,10 +1454,9 @@ PPC_OP(fneg)
} }
/* Load and store */ /* Load and store */
#if defined(CONFIG_USER_ONLY)
#define MEMSUFFIX _raw #define MEMSUFFIX _raw
#include "op_mem.h" #include "op_mem.h"
#else #if !defined(CONFIG_USER_ONLY)
#define MEMSUFFIX _user #define MEMSUFFIX _user
#include "op_mem.h" #include "op_mem.h"
...@@ -1460,8 +1470,11 @@ PPC_OP(rfi) ...@@ -1460,8 +1470,11 @@ PPC_OP(rfi)
T0 = regs->spr[SRR1] & ~0xFFFF0000; T0 = regs->spr[SRR1] & ~0xFFFF0000;
do_store_msr(); do_store_msr();
do_tlbia(); do_tlbia();
#if defined (DEBUG_OP)
dump_rfi(); dump_rfi();
#endif
regs->nip = regs->spr[SRR0] & ~0x00000003; regs->nip = regs->spr[SRR0] & ~0x00000003;
do_queue_exception(EXCP_RFI);
if (env->exceptions != 0) { if (env->exceptions != 0) {
do_check_exception_state(); do_check_exception_state();
} }
......
...@@ -20,10 +20,9 @@ ...@@ -20,10 +20,9 @@
#include <math.h> #include <math.h>
#include "exec.h" #include "exec.h"
#if defined(CONFIG_USER_ONLY)
#define MEMSUFFIX _raw #define MEMSUFFIX _raw
#include "op_helper_mem.h" #include "op_helper_mem.h"
#else #if !defined(CONFIG_USER_ONLY)
#define MEMSUFFIX _user #define MEMSUFFIX _user
#include "op_helper_mem.h" #include "op_helper_mem.h"
#define MEMSUFFIX _kernel #define MEMSUFFIX _kernel
...@@ -122,8 +121,7 @@ void do_load_msr (void) ...@@ -122,8 +121,7 @@ void do_load_msr (void)
void do_store_msr (void) void do_store_msr (void)
{ {
if (((T0 >> MSR_IR) & 0x01) != msr_ir || if (((T0 >> MSR_IR) & 0x01) != msr_ir ||
((T0 >> MSR_DR) & 0x01) != msr_dr || ((T0 >> MSR_DR) & 0x01) != msr_dr) {
((T0 >> MSR_PR) & 0x01) != msr_pr) {
/* Flush all tlb when changing translation mode or privilege level */ /* Flush all tlb when changing translation mode or privilege level */
do_tlbia(); do_tlbia();
} }
...@@ -371,44 +369,18 @@ void do_tlbie (void) ...@@ -371,44 +369,18 @@ void do_tlbie (void)
/*****************************************************************************/ /*****************************************************************************/
/* Special helpers for debug */ /* Special helpers for debug */
extern FILE *stdout;
void dump_state (void)
{
cpu_ppc_dump_state(env, stdout, 0);
}
void dump_rfi (void) void dump_rfi (void)
{ {
#if 0 #if 0
printf("Return from interrupt\n"); printf("Return from interrupt %d => 0x%08x\n", pos, env->nip);
printf("nip=0x%08x LR=0x%08x CTR=0x%08x MSR=0x%08x\n", // cpu_ppc_dump_state(env, stdout, 0);
env->nip, env->lr, env->ctr,
(msr_pow << MSR_POW) | (msr_ile << MSR_ILE) | (msr_ee << MSR_EE) |
(msr_pr << MSR_PR) | (msr_fp << MSR_FP) | (msr_me << MSR_ME) |
(msr_fe0 << MSR_FE0) | (msr_se << MSR_SE) | (msr_be << MSR_BE) |
(msr_fe1 << MSR_FE1) | (msr_ip << MSR_IP) | (msr_ir << MSR_IR) |
(msr_dr << MSR_DR) | (msr_ri << MSR_RI) | (msr_le << MSR_LE));
{
int i;
for (i = 0; i < 32; i++) {
if ((i & 7) == 0)
printf("GPR%02d:", i);
printf(" %08x", env->gpr[i]);
if ((i & 7) == 7)
printf("\n");
}
printf("CR: 0x");
for (i = 0; i < 8; i++)
printf("%01x", env->crf[i]);
printf(" [");
for (i = 0; i < 8; i++) {
char a = '-';
if (env->crf[i] & 0x08)
a = 'L';
else if (env->crf[i] & 0x04)
a = 'G';
else if (env->crf[i] & 0x02)
a = 'E';
printf(" %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
}
printf(" ] ");
}
printf("TB: 0x%08x %08x\n", env->tb[1], env->tb[0]);
printf("SRR0 0x%08x SRR1 0x%08x\n", env->spr[SRR0], env->spr[SRR1]);
#endif #endif
} }
......
...@@ -2168,22 +2168,48 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) ...@@ -2168,22 +2168,48 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
/* dcbf */ /* dcbf */
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE) GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
{ {
if (rA(ctx->opcode) == 0) {
gen_op_load_gpr_T0(rB(ctx->opcode));
} else {
gen_op_load_gpr_T0(rA(ctx->opcode));
gen_op_load_gpr_T1(rB(ctx->opcode));
gen_op_add();
}
op_ldst(lbz);
} }
/* dcbi (Supervisor only) */ /* dcbi (Supervisor only) */
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE) GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
{ {
#if !defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
if (!ctx->supervisor) RET_PRIVOPC();
#endif #else
{ if (!ctx->supervisor) {
RET_PRIVOPC(); RET_PRIVOPC();
} }
if (rA(ctx->opcode) == 0) {
gen_op_load_gpr_T0(rB(ctx->opcode));
} else {
gen_op_load_gpr_T0(rA(ctx->opcode));
gen_op_load_gpr_T1(rB(ctx->opcode));
gen_op_add();
}
op_ldst(lbz);
op_ldst(stb);
#endif
} }
/* dcdst */ /* dcdst */
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE) GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
{ {
if (rA(ctx->opcode) == 0) {
gen_op_load_gpr_T0(rB(ctx->opcode));
} else {
gen_op_load_gpr_T0(rA(ctx->opcode));
gen_op_load_gpr_T1(rB(ctx->opcode));
gen_op_add();
}
op_ldst(lbz);
} }
/* dcbt */ /* dcbt */
...@@ -2863,7 +2889,7 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) ...@@ -2863,7 +2889,7 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
fprintf(f, "nip=0x%08x LR=0x%08x CTR=0x%08x XER=0x%08x " fprintf(f, "nip=0x%08x LR=0x%08x CTR=0x%08x XER=0x%08x "
"MSR=0x%08x\n", env->nip, env->lr, env->ctr, "MSR=0x%08x\n", env->nip, env->lr, env->ctr,
_load_xer(), _load_msr()); _load_xer(env), _load_msr(env));
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
if ((i & 7) == 0) if ((i & 7) == 0)
fprintf(f, "GPR%02d:", i); fprintf(f, "GPR%02d:", i);
...@@ -2894,8 +2920,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) ...@@ -2894,8 +2920,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
if ((i & 3) == 3) if ((i & 3) == 3)
fprintf(f, "\n"); fprintf(f, "\n");
} }
fprintf(f, "SRR0 0x%08x SRR1 0x%08x\n", fprintf(f, "SRR0 0x%08x SRR1 0x%08x DECR=0x%08x excp:0x%08x\n",
env->spr[SRR0], env->spr[SRR1]); env->spr[SRR0], env->spr[SRR1], env->decr, env->exceptions);
fprintf(f, "reservation 0x%08x\n", env->reserve); fprintf(f, "reservation 0x%08x\n", env->reserve);
fflush(f); fflush(f);
} }
...@@ -2934,6 +2960,7 @@ CPUPPCState *cpu_ppc_init(void) ...@@ -2934,6 +2960,7 @@ CPUPPCState *cpu_ppc_init(void)
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
msr_pr = 1; msr_pr = 1;
#endif #endif
env->access_type = ACCESS_INT;
return env; return env;
} }
...@@ -2977,6 +3004,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, ...@@ -2977,6 +3004,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
/* Single step trace mode */ /* Single step trace mode */
msr_se = 1; msr_se = 1;
#endif #endif
env->access_type = ACCESS_CODE;
/* Set env in case of segfault during code fetch */ /* Set env in case of segfault during code fetch */
while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) { while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) {
if (search_pc) { if (search_pc) {
...@@ -3073,9 +3101,8 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, ...@@ -3073,9 +3101,8 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
ctx.exception = EXCP_TRACE; ctx.exception = EXCP_TRACE;
} }
} }
/* if too long translation, stop generation too */ /* if we reach a page boundary, stop generation */
if (gen_opc_ptr >= gen_opc_end || if (((uint32_t)ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) {
((uint32_t)ctx.nip - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
if (ctx.exception == EXCP_NONE) { if (ctx.exception == EXCP_NONE) {
gen_op_b((long)ctx.tb, (uint32_t)ctx.nip); gen_op_b((long)ctx.tb, (uint32_t)ctx.nip);
ctx.exception = EXCP_BRANCH; ctx.exception = EXCP_BRANCH;
...@@ -3111,6 +3138,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, ...@@ -3111,6 +3138,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
} else { } else {
tb->size = (uint32_t)ctx.nip - pc_start; tb->size = (uint32_t)ctx.nip - pc_start;
} }
env->access_type = ACCESS_INT;
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (loglevel > 0) { if (loglevel > 0) {
fprintf(logfile, "---------------- excp: %04x\n", ctx.exception); fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
......
...@@ -230,6 +230,9 @@ int cpu_restore_state(TranslationBlock *tb, ...@@ -230,6 +230,9 @@ int cpu_restore_state(TranslationBlock *tb,
CASE3(lfs): CASE3(lfs):
type = ACCESS_FLOAT; type = ACCESS_FLOAT;
break; break;
CASE3(lwarx):
type = ACCESS_RES;
break;
CASE3(stwcx): CASE3(stwcx):
type = ACCESS_RES; type = ACCESS_RES;
break; break;
......
...@@ -68,6 +68,8 @@ extern void __sigaction(); ...@@ -68,6 +68,8 @@ extern void __sigaction();
#include "exec-all.h" #include "exec-all.h"
//#define DO_TB_FLUSH
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
//#define DEBUG_UNUSED_IOPORT //#define DEBUG_UNUSED_IOPORT
...@@ -1201,6 +1203,9 @@ int qemu_loadvm(const char *filename) ...@@ -1201,6 +1203,9 @@ int qemu_loadvm(const char *filename)
goto the_end; goto the_end;
} }
for(;;) { for(;;) {
#if defined (DO_TB_FLUSH)
tb_flush();
#endif
len = qemu_get_byte(f); len = qemu_get_byte(f);
if (feof(f)) if (feof(f))
break; break;
...@@ -1380,6 +1385,15 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) ...@@ -1380,6 +1385,15 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
return 0; return 0;
} }
#elif defined(TARGET_PPC)
void cpu_save(QEMUFile *f, void *opaque)
{
}
int cpu_load(QEMUFile *f, void *opaque, int version_id)
{
return 0;
}
#else #else
#warning No CPU save/restore functions #warning No CPU save/restore functions
...@@ -1706,6 +1720,7 @@ int main(int argc, char **argv) ...@@ -1706,6 +1720,7 @@ int main(int argc, char **argv)
const char *kernel_filename, *kernel_cmdline; const char *kernel_filename, *kernel_cmdline;
DisplayState *ds = &display_state; DisplayState *ds = &display_state;
int cyls, heads, secs; int cyls, heads, secs;
int start_emulation = 1;
uint8_t macaddr[6]; uint8_t macaddr[6];
#if !defined(CONFIG_SOFTMMU) #if !defined(CONFIG_SOFTMMU)
...@@ -1744,7 +1759,7 @@ int main(int argc, char **argv) ...@@ -1744,7 +1759,7 @@ int main(int argc, char **argv)
nd_table[i].fd = -1; nd_table[i].fd = -1;
for(;;) { for(;;) {
c = getopt_long_only(argc, argv, "hm:d:n:sp:L:", long_options, &long_index); c = getopt_long_only(argc, argv, "hm:d:n:sp:L:S", long_options, &long_index);
if (c == -1) if (c == -1)
break; break;
switch(c) { switch(c) {
...@@ -1915,6 +1930,9 @@ int main(int argc, char **argv) ...@@ -1915,6 +1930,9 @@ int main(int argc, char **argv)
case 'L': case 'L':
bios_dir = optarg; bios_dir = optarg;
break; break;
case 'S':
start_emulation = 0;
break;
} }
} }
...@@ -2121,7 +2139,9 @@ int main(int argc, char **argv) ...@@ -2121,7 +2139,9 @@ int main(int argc, char **argv)
ds, fd_filename, snapshot, ds, fd_filename, snapshot,
kernel_filename, kernel_cmdline, initrd_filename); kernel_filename, kernel_cmdline, initrd_filename);
#elif defined(TARGET_PPC) #elif defined(TARGET_PPC)
ppc_init(); ppc_init(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
kernel_filename, kernel_cmdline, initrd_filename);
#endif #endif
/* launched after the device init so that it can display or not a /* launched after the device init so that it can display or not a
...@@ -2142,6 +2162,7 @@ int main(int argc, char **argv) ...@@ -2142,6 +2162,7 @@ int main(int argc, char **argv)
} }
} else } else
#endif #endif
if (start_emulation)
{ {
vm_start(); vm_start();
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册