Commit a541f297 authored by bellard's avatar bellard

PowerPC system emulation fixes (Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@722 c046a42c-6fe2-441c-8c8c-71466251a162
parent df475d18
......@@ -16,8 +16,12 @@ DYNGEN=../dyngen$(EXESUF)
QEMU_USER=qemu-$(TARGET_ARCH)
# system emulator name
ifdef CONFIG_SOFTMMU
ifeq ($(TARGET_ARCH), i386)
QEMU_SYSTEM=qemu$(EXESUF)
else
QEMU_SYSTEM=qemu-system-$(TARGET_ARCH)$(EXESUF)
endif
else
QEMU_SYSTEM=qemu-fast
endif
......@@ -222,14 +226,23 @@ ifeq ($(ARCH),alpha)
endif
# must use static linking to avoid leaving stuff in virtual address space
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
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
VL_OBJS=vl.o osdep.o block.o monitor.o
ifeq ($(TARGET_ARCH), i386)
# Hardware support
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
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
ifdef CONFIG_SDL
VL_OBJS+=sdl.o
......
......@@ -27,7 +27,7 @@ ar="ar"
make="make"
strip="strip"
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
i386|i486|i586|i686|i86pc|BePC)
cpu="i386"
......
......@@ -190,7 +190,7 @@ int cpu_exec(CPUState *env1)
(env->eflags & IF_MASK) &&
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno;
intno = cpu_x86_get_pic_interrupt(env);
intno = cpu_get_pic_interrupt(env);
if (loglevel & CPU_LOG_TB_IN_ASM) {
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)
#endif
if (__builtin_expect(env->tlb_read[is_user][index].address !=
(addr & TARGET_PAGE_MASK), 0)) {
#if defined (TARGET_PPC)
env->access_type = ACCESS_CODE;
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;
}
......
......@@ -914,7 +914,7 @@ static void tb_reset_jump_recursive(TranslationBlock *tb)
breakpoint is reached */
int cpu_breakpoint_insert(CPUState *env, uint32_t pc)
{
#if defined(TARGET_I386)
#if defined(TARGET_I386) || defined(TARGET_PPC)
int i;
for(i = 0; i < env->nb_breakpoints; i++) {
......@@ -935,7 +935,7 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc)
/* remove a breakpoint */
int cpu_breakpoint_remove(CPUState *env, uint32_t pc)
{
#if defined(TARGET_I386)
#if defined(TARGET_I386) || defined(TARGET_PPC)
int i;
for(i = 0; i < env->nb_breakpoints; i++) {
if (env->breakpoints[i] == pc)
......@@ -957,7 +957,7 @@ int cpu_breakpoint_remove(CPUState *env, uint32_t pc)
CPU loop after each instruction */
void cpu_single_step(CPUState *env, int enabled)
{
#if defined(TARGET_I386)
#if defined(TARGET_I386) || defined(TARGET_PPC)
if (env->singlestep_enabled != enabled) {
env->singlestep_enabled = enabled;
/* 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)
}
#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[2] = v >> 8;
p[1] = v >> 16;
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)
{
uint32_t tmp;
uint32_t *registers = (uint32_t *)mem_buf, tmp;
int i;
/* fill in gprs */
for(i = 0; i < 8; i++) {
to_le32(mem_buf + i * 4, env->gpr[i]);
for(i = 0; i < 32; i++) {
to_le32(&registers[i], env->gpr[i]);
}
/* fill in fprs */
for (i = 0; i < 32; i++) {
to_le32(mem_buf + (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) + 32], *((uint32_t *)&env->fpr[i]));
to_le32(&registers[(i * 2) + 33], *((uint32_t *)&env->fpr[i] + 1));
}
/* nip, msr, ccr, lnk, ctr, xer, mq */
to_le32(mem_buf + 96, tswapl(env->nip));
to_le32(mem_buf + 97, tswapl(_load_msr()));
to_le32(mem_buf + 98, 0);
to_le32(&registers[96], (uint32_t)env->nip/* - 4*/);
to_le32(&registers[97], _load_msr(env));
tmp = 0;
for (i = 0; i < 8; i++)
tmp |= env->crf[i] << (32 - (i * 4));
to_le32(mem_buf + 98, tmp);
to_le32(mem_buf + 99, tswapl(env->lr));
to_le32(mem_buf + 100, tswapl(env->ctr));
to_le32(mem_buf + 101, tswapl(_load_xer()));
to_le32(mem_buf + 102, 0);
return 102;
tmp |= env->crf[i] << (32 - ((i + 1) * 4));
to_le32(&registers[98], tmp);
to_le32(&registers[99], env->lr);
to_le32(&registers[100], env->ctr);
to_le32(&registers[101], _load_xer(env));
to_le32(&registers[102], 0);
return 103 * 4;
}
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 */
for (i = 0; i < 32; i++) {
env->gpr[i] = tswapl(registers[i]);
env->gpr[i] = from_le32(&registers[i]);
}
/* fill in fprs */
for (i = 0; i < 32; i++) {
*((uint32_t *)&env->fpr[i]) = tswapl(registers[(i * 2) + 32]);
*((uint32_t *)&env->fpr[i] + 1) = tswapl(registers[(i * 2) + 33]);
*((uint32_t *)&env->fpr[i]) = from_le32(&registers[(i * 2) + 32]);
*((uint32_t *)&env->fpr[i] + 1) = from_le32(&registers[(i * 2) + 33]);
}
/* nip, msr, ccr, lnk, ctr, xer, mq */
env->nip = tswapl(registers[96]);
_store_msr(tswapl(registers[97]));
registers[98] = tswapl(registers[98]);
env->nip = from_le32(&registers[96]);
_store_msr(env, from_le32(&registers[97]));
registers[98] = from_le32(&registers[98]);
for (i = 0; i < 8; i++)
env->crf[i] = (registers[98] >> (32 - (i * 4))) & 0xF;
env->lr = tswapl(registers[99]);
env->ctr = tswapl(registers[100]);
_store_xer(tswapl(registers[101]));
env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF;
env->lr = from_le32(&registers[99]);
env->ctr = from_le32(&registers[100]);
_store_xer(env, from_le32(&registers[101]));
}
#else
......
This diff is collapsed.
......@@ -174,7 +174,7 @@ static inline void pic_intack(PicState *s, int irq)
s->irr &= ~(1 << irq);
}
int cpu_x86_get_pic_interrupt(CPUState *env)
int cpu_get_pic_interrupt(CPUState *env)
{
int irq, irq2, intno;
......
This diff is collapsed.
#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)
{
int isr;
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)
pic_set_irq(s->irq, 1);
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);
}
This diff is collapsed.
......@@ -94,15 +94,15 @@ int cpu_inl(CPUState *env, int addr)
return 0;
}
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
int cpu_x86_get_pic_interrupt(CPUState *env)
int cpu_get_pic_interrupt(CPUState *env)
{
return -1;
}
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
int flags)
{
......@@ -441,7 +441,6 @@ void cpu_loop (CPUSPARCState *env)
#endif
#ifdef TARGET_PPC
void cpu_loop(CPUPPCState *env)
{
target_siginfo_t info;
......@@ -769,6 +768,8 @@ void cpu_loop(CPUPPCState *env)
case EXCP_INTERRUPT:
/* Don't know why this should ever happen... */
break;
case EXCP_DEBUG:
break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
......
......@@ -2475,6 +2475,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
}
#endif
break;
#ifdef TARGET_NR_getdents64
case TARGET_NR_getdents64:
{
struct dirent64 *dirp = (void *)arg2;
......@@ -2498,6 +2499,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
}
}
break;
#endif /* TARGET_NR_getdents64 */
case TARGET_NR__newselect:
ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4,
(void *)arg5);
......
......@@ -530,6 +530,47 @@ typedef struct MonitorDef {
int (*get_value)(struct MonitorDef *md);
} 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[] = {
#ifdef TARGET_I386
{ "eax", offsetof(CPUState, regs[0]) },
......@@ -542,6 +583,65 @@ static MonitorDef monitor_defs[] = {
{ "esi", offsetof(CPUState, regs[7]) },
{ "eflags", offsetof(CPUState, eflags) },
{ "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
{ NULL },
};
......
......@@ -20,9 +20,6 @@
#if !defined (__CPU_PPC_H__)
#define __CPU_PPC_H__
#include <endian.h>
#include <asm/byteorder.h>
#define TARGET_LONG_BITS 32
#include "cpu-defs.h"
......@@ -157,14 +154,26 @@ typedef struct CPUPPCState {
int error_code;
int access_type; /* when a memory exception occurs, the access
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 errors[16];
uint32_t errors[32];
#endif
int user_mode_only; /* user mode only simulation */
struct TranslationBlock *current_tb; /* currently executing TB */
/* 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_write[2][CPU_TLB_SIZE];
/* ice debug support */
uint32_t breakpoints[MAX_BREAKPOINTS];
int nb_breakpoints;
int brkstate;
int singlestep_enabled;
/* user data */
void *opaque;
} CPUPPCState;
......@@ -179,14 +188,21 @@ struct siginfo;
int cpu_ppc_signal_handler(int host_signum, struct siginfo *info,
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_ppc_dump_state(CPUPPCState *env, FILE *f, int flags);
void dump_stack (CPUPPCState *env);
uint32_t _load_xer (void);
void _store_xer (uint32_t value);
uint32_t _load_msr (void);
void _store_msr (uint32_t value);
void do_interrupt (CPUPPCState *env);
uint32_t _load_xer (CPUPPCState *env);
void _store_xer (CPUPPCState *env, uint32_t value);
uint32_t _load_msr (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
#include "cpu-all.h"
......@@ -277,14 +293,6 @@ void do_interrupt (CPUPPCState *env);
#define TARGET_PAGE_BITS 12
#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 :
* may be needed for precise access rights control and precise exceptions.
*/
......@@ -351,12 +359,14 @@ enum {
/* flags for EXCP_DSI */
EXCP_DSI_DIRECT = 0x10,
EXCP_DSI_STORE = 0x20,
EXCP_ECXW = 0x40,
EXCP_DSI_ECXW = 0x40,
/* Exception subtypes for EXCP_ISI */
EXCP_ISI_TRANSLATE = 0x01, /* Code address can't be translated */
EXCP_ISI_NOEXEC = 0x02, /* Try to fetch from a data segment */
EXCP_ISI_GUARD = 0x03, /* Fetch from guarded memory */
EXCP_ISI_PROT = 0x04, /* Memory protection violation */
EXCP_ISI_DIRECT = 0x05, /* Trying to fetch from *
* a direct store segment */
/* Exception subtypes for EXCP_ALIGN */
EXCP_ALIGN_FP = 0x01, /* FP alignment exception */
EXCP_ALIGN_LST = 0x02, /* Unaligned mult/extern load/store */
......
......@@ -36,7 +36,11 @@ register uint32_t T2 asm(AREG3);
#define FTS1 ((float)env->ft1)
#define FTS2 ((float)env->ft2)
#if defined (DEBUG_OP)
#define RETURN() __asm__ __volatile__("nop");
#else
#define RETURN() __asm__ __volatile__("");
#endif
#include "cpu.h"
#include "exec-all.h"
......@@ -149,6 +153,7 @@ void do_icbi (void);
void do_tlbia (void);
void do_tlbie (void);
void dump_state (void);
void dump_rfi (void);
void dump_store_sr (int srnum);
void dump_store_ibat (int ul, int nr);
......
This diff is collapsed.
......@@ -18,11 +18,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//#define DEBUG_OP
#include "config.h"
#include "exec.h"
//#define DEBUG_OP
#define regs (env)
#define Ts0 (int32_t)T0
#define Ts1 (int32_t)T1
......@@ -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 */
PPC_OP(load_srin)
{
......@@ -1443,10 +1454,9 @@ PPC_OP(fneg)
}
/* Load and store */
#if defined(CONFIG_USER_ONLY)
#define MEMSUFFIX _raw
#include "op_mem.h"
#else
#if !defined(CONFIG_USER_ONLY)
#define MEMSUFFIX _user
#include "op_mem.h"
......@@ -1460,8 +1470,11 @@ PPC_OP(rfi)
T0 = regs->spr[SRR1] & ~0xFFFF0000;
do_store_msr();
do_tlbia();
#if defined (DEBUG_OP)
dump_rfi();
#endif
regs->nip = regs->spr[SRR0] & ~0x00000003;
do_queue_exception(EXCP_RFI);
if (env->exceptions != 0) {
do_check_exception_state();
}
......
......@@ -20,10 +20,9 @@
#include <math.h>
#include "exec.h"
#if defined(CONFIG_USER_ONLY)
#define MEMSUFFIX _raw
#include "op_helper_mem.h"
#else
#if !defined(CONFIG_USER_ONLY)
#define MEMSUFFIX _user
#include "op_helper_mem.h"
#define MEMSUFFIX _kernel
......@@ -122,8 +121,7 @@ void do_load_msr (void)
void do_store_msr (void)
{
if (((T0 >> MSR_IR) & 0x01) != msr_ir ||
((T0 >> MSR_DR) & 0x01) != msr_dr ||
((T0 >> MSR_PR) & 0x01) != msr_pr) {
((T0 >> MSR_DR) & 0x01) != msr_dr) {
/* Flush all tlb when changing translation mode or privilege level */
do_tlbia();
}
......@@ -371,44 +369,18 @@ void do_tlbie (void)
/*****************************************************************************/
/* Special helpers for debug */
extern FILE *stdout;
void dump_state (void)
{
cpu_ppc_dump_state(env, stdout, 0);
}
void dump_rfi (void)
{
#if 0
printf("Return from interrupt\n");
printf("nip=0x%08x LR=0x%08x CTR=0x%08x MSR=0x%08x\n",
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]);
printf("Return from interrupt %d => 0x%08x\n", pos, env->nip);
// cpu_ppc_dump_state(env, stdout, 0);
#endif
}
......
......@@ -2168,22 +2168,48 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
/* dcbf */
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) */
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
{
#if !defined(CONFIG_USER_ONLY)
if (!ctx->supervisor)
#endif
{
#if defined(CONFIG_USER_ONLY)
RET_PRIVOPC();
#else
if (!ctx->supervisor) {
RET_PRIVOPC();
}