diff --git a/plat/linuxppc/emu/emu.c b/plat/linuxppc/emu/emu.c index 29404390c..75800807e 100644 --- a/plat/linuxppc/emu/emu.c +++ b/plat/linuxppc/emu/emu.c @@ -34,6 +34,16 @@ static inline uint32_t reg0(uint8_t n) return cpu.gpr[n]; } +static inline uint64_t tobytes(double n) +{ + return *(uint64_t*)&n; +} + +static inline double fpr(uint8_t n) +{ + return *(double*)&cpu.fpr[n]; +} + static inline uint32_t ext8(int8_t n) { return (n << 24) >> 24; @@ -72,6 +82,12 @@ static void setcr0(bool setcr0, uint32_t value) } } +static void setcr1(bool setcr1, uint64_t value) +{ + if (setcr1) + fatal("setcr1 not implemented yet"); +} + static void mcrf(uint8_t destfield, uint8_t srcfield) { fatal("mcrf not supported yet"); @@ -220,7 +236,7 @@ static void mtcrf(uint8_t fxm, uint32_t value) static void dispatch(uint32_t value) { #include "dispatcher.h" - fatal("unimplemented instruction 0x%0x", value); + fatal("unimplemented instruction 0x%0x (major opcode %d)", value, value>>26); } void dump_state(FILE* stream) diff --git a/plat/linuxppc/emu/emu.h b/plat/linuxppc/emu/emu.h index 58fad27ec..622a02536 100644 --- a/plat/linuxppc/emu/emu.h +++ b/plat/linuxppc/emu/emu.h @@ -22,9 +22,11 @@ extern cpu_t cpu; extern uint32_t read_byte(uint32_t address); extern uint32_t read_word(uint32_t address); extern uint32_t read_long(uint32_t address); +extern uint64_t read_double(uint32_t address); extern void write_byte(uint32_t address, uint32_t value); extern void write_word(uint32_t address, uint32_t value); extern void write_long(uint32_t address, uint32_t value); +extern void write_double(uint32_t address, uint64_t value); extern void system_call(uint8_t trapno); diff --git a/plat/linuxppc/emu/instructions.dat b/plat/linuxppc/emu/instructions.dat index 2203f9ccf..09b2f3ec0 100644 --- a/plat/linuxppc/emu/instructions.dat +++ b/plat/linuxppc/emu/instructions.dat @@ -47,16 +47,16 @@ # Fixed point stores -<38--> write_byte(reg0(RA) + ext16(D), RS); -<31--><215----->. write_byte(reg0(RA) + reg(RB), RS); +<38--> write_byte(reg0(RA) + ext16(D), reg(RS)); +<31--><215----->. write_byte(reg0(RA) + reg(RB), reg(RS)); <39--> uint32_t ea = reg(RA) + ext16(D); write_byte(ea, reg(RS)); cpu.gpr[RA] = ea; <31--><247----->. uint32_t ea = reg(RA) + reg(RB); write_byte(ea, reg(RS)); cpu.gpr[RA] = ea; -<44--> write_word(reg0(RA) + ext16(D), RS); -<31--><407----->. write_word(reg0(RA) + reg(RB), RS); +<44--> write_word(reg0(RA) + ext16(D), reg(RS)); +<31--><407----->. write_word(reg0(RA) + reg(RB), reg(RS)); <45--> uint32_t ea = reg(RA) + ext16(D); write_word(ea, reg(RS)); cpu.gpr[RA] = ea; <31--><439----->. uint32_t ea = reg(RA) + reg(RB); write_word(ea, reg(RS)); cpu.gpr[RA] = ea; -<36--> write_long(reg0(RA) + ext16(D), RS); -<31--><151----->. write_long(reg0(RA) + reg(RB), RS); +<36--> write_long(reg0(RA) + ext16(D), reg(RS)); +<31--><151----->. write_long(reg0(RA) + reg(RB), reg(RS)); <37--> uint32_t ea = reg(RA) + ext16(D); write_long(ea, reg(RS)); cpu.gpr[RA] = ea; <31--><183----->. uint32_t ea = reg(RA) + reg(RB); write_long(ea, reg(RS)); cpu.gpr[RA] = ea; @@ -147,3 +147,21 @@ <31-->0.<144----->. mtcrf(FXM, reg(RS)); <31-->0.........<19------>. cpu.gpr[RT] = cpu.cr; +# Floating point loads + +<50-->. cpu.fpr[FRT] = read_double(reg0(RA) + ext16(D)); +<31--><599----->. cpu.gpr[FRT] = read_double(reg0(RA) + reg(RB)); +<51--> uint32_t ea = reg(RA) + ext16(D); cpu.fpr[FRT] = read_byte(ea); cpu.gpr[RA] = ea; +<31--><631----->. uint32_t ea = reg(RA) + reg(RB); cpu.fpr[FRT] = read_long(ea); cpu.gpr[RA] = ea; + +# Floating point stores + +<54-->. write_double(read_double(reg0(RA) + ext16(D)), cpu.fpr[FRS]); +<31--><727----->. write_double(reg0(RA) + reg(RB), cpu.fpr[FRS]); +<55--> uint32_t ea = reg(RA) + ext16(D); write_double(ea, cpu.fpr[FRS]); cpu.gpr[RA] = ea; +<31--><759----->. uint32_t ea = reg(RA) + reg(RB); write_long(ea, cpu.fpr[FRS]); cpu.gpr[RA] = ea; + +# Floating point arithmetic + +<63-->.....<72------>R setcr1(R, cpu.fpr[FRT] = cpu.fpr[FRB]); +<63--><20------>R setcr1(R, cpu.fpr[FRT] = tobytes(fpr(FRA) - fpr(FRB))); diff --git a/plat/linuxppc/emu/main.c b/plat/linuxppc/emu/main.c index b6ca92ea7..fe52aa566 100755 --- a/plat/linuxppc/emu/main.c +++ b/plat/linuxppc/emu/main.c @@ -17,6 +17,8 @@ #define INIT_SP RAM_TOP #define INIT_PC 0x08000054 +#define EXIT_PC 0xdeaddead + /* Read/write macros */ #define READ_BYTE(BASE, ADDR) (BASE)[ADDR] #define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) | \ @@ -71,6 +73,11 @@ static uint32_t transform_address(uint32_t address) return a; } +uint64_t read_double(uint32_t address) +{ + return ((uint64_t)read_long(address+0) << 32) | read_long(address+4); +} + uint32_t read_long(uint32_t address) { uint32_t v = READ_LONG(ram, transform_address(address)); @@ -80,7 +87,6 @@ uint32_t read_long(uint32_t address) return v; } - uint32_t read_word(uint32_t address) { return READ_WORD(ram, transform_address(address)); @@ -109,6 +115,12 @@ void write_long(uint32_t address, uint32_t value) WRITE_LONG(ram, transform_address(address), value); } +void write_double(uint32_t address, uint64_t value) +{ + write_long(address+0, value>>32); + write_long(address+4, value); +} + void system_call(uint8_t trapno) { cpu.cr &= ~(1<<28); /* reset summary overflow (for success) */ @@ -130,6 +142,21 @@ void system_call(uint8_t trapno) break; } + case 45: /* brk */ + { + uint32_t newpos = cpu.gpr[3]; + if (newpos == 0) + cpu.gpr[4] = brkpos; + else if ((newpos < brkbase) || (newpos >= BRK_TOP)) + cpu.gpr[4] = -ENOMEM; + else + { + brkpos = newpos; + cpu.gpr[4] = 0; + } + break; + } + case 126: /* sigprocmask */ cpu.gpr[4] = 0; break; @@ -212,7 +239,8 @@ int main(int argc, char* argv[]) cpu.cia = entrypoint; } - for (;;) + cpu.lr = EXIT_PC; + while (cpu.cia != EXIT_PC) { #if 0 dump_state(stderr);