Implement a non-functional skeleton of the PowerPC emulator (with, hopefully,

most of the instruction decode done).
This commit is contained in:
David Given 2018-06-14 03:07:36 -07:00
parent c9e5190a12
commit b71145f79d
7 changed files with 628 additions and 1 deletions

View file

@ -0,0 +1,28 @@
normalrule {
name = "dispatcher",
ins = {
"./mkdispatcher.lua",
"./instructions.dat"
},
outleaves = {
"dispatcher.h"
},
commands = {
"$(LUA) %{ins[1]} < %{ins[2]} > %{outs}"
}
}
clibrary {
name = "dispatcher_lib",
srcs = {},
hdrs = { "+dispatcher" }
}
cprogram {
name = "emuppc",
srcs = { "./*.c" },
deps = {
"+dispatcher_lib"
}
}

168
plat/linuxppc/emu/emu.c Normal file
View file

@ -0,0 +1,168 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <strings.h>
#include <byteswap.h>
#include "emu.h"
cpu_t cpu;
static inline bool carry(void)
{
fatal("carry() not supported yet");
}
#define swb16(x) bswap_16(x)
#define swb32(x) bswap_32(x)
static inline uint32_t reg(uint8_t n)
{
return cpu.gpr[n];
}
static inline uint32_t reg0(uint8_t n)
{
if (n == 0)
return 0;
return cpu.gpr[n];
}
static inline uint32_t ext8(int8_t n)
{
return (n << 24) >> 24;
}
static inline uint32_t ext16(int16_t n)
{
return (n << 16) >> 16;
}
static bool getcr(uint8_t bit)
{
bit = 31 - bit; /* note PowerPC bit numbering */
return cpu.cr & (1<<bit);
}
static void setcr(uint8_t bit, bool value)
{
bit = 31 - bit; /* note PowerPC bit numbering */
cpu.cr = cpu.cr & (1<<bit) | (value<<bit);
}
static void setcr0(bool setcr0, uint32_t value)
{
if (setcr0)
fatal("setcr0 not supported yet");
}
static void mcrf(uint8_t destfield, uint8_t srcfield)
{
fatal("mcrf not supported yet");
}
static void branch(uint8_t bo, uint8_t bi, uint32_t dest, bool a_bit, bool l_bit)
{
fatal("branch not supported yet");
}
static void read_multiple(uint32_t address, uint8_t reg)
{
fatal("read_multiple not supported yet");
}
static void write_multiple(uint32_t address, uint8_t reg)
{
fatal("write_multiple not supported yet");
}
static void read_string(uint32_t address, uint8_t reg, uint8_t bytes)
{
fatal("read_string not supported yet");
}
static void write_string(uint32_t address, uint8_t reg, uint8_t bytes)
{
fatal("write_string not supported yet");
}
static uint32_t addo(uint32_t a, uint32_t b, uint32_t c, bool set_o, bool set_c)
{
if (set_o || set_c)
fatal("can't use O or C bits in add yet");
return a + b + c;
}
static uint32_t mulo(uint32_t a, uint32_t b, bool set_o)
{
if (set_o)
fatal("can't use O bit in mul yet");
return a * b;
}
static int32_t divo(int32_t a, int32_t b, bool set_o)
{
if (set_o)
fatal("can't use O bit in div yet");
return a / b;
}
static uint32_t divuo(uint32_t a, uint32_t b, bool set_o)
{
if (set_o)
fatal("can't use O bit in divu yet");
return a / b;
}
static void compares(int32_t a, int32_t b, uint8_t field)
{
fatal("compares not supported yet");
}
static void compareu(uint32_t a, uint32_t b, uint8_t field)
{
fatal("compareu not supported yet");
}
static uint32_t cntlzw(uint32_t source)
{
return 32 - ffs(source);
}
static uint32_t popcntb(uint32_t source)
{
fatal("popcntb not supported");
}
static uint32_t rlwnm(uint32_t source, uint8_t shift, uint8_t mb, uint8_t me)
{
fatal("rlwnm not supported");
}
static uint32_t rlwmi(uint32_t source, uint8_t shift, uint8_t mb, uint8_t me)
{
fatal("rlwmi not supported");
}
static void mtcrf(uint8_t fxm, uint32_t value)
{
fatal("mtcrf not supported");
}
static void dispatch(uint32_t value)
{
#include "dispatcher.h"
fatal("unimplemented instruction 0x%0x", value);
}
static void single_step(void)
{
uint32_t value = read_long(cpu.cia);
cpu.nia = cpu.cia + 4;
dispatch(value);
cpu.cia = cpu.nia;
}

32
plat/linuxppc/emu/emu.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef EMU_H
#define EMU_H
extern void fatal(char* fmt, ...);
typedef struct
{
uint32_t gpr[32];
uint64_t fpr[32];
uint32_t cr;
uint32_t ctr;
uint32_t lr;
uint32_t xer;
uint32_t fpscr;
uint32_t cia;
uint32_t nia;
}
cpu_t;
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 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 system_call(uint8_t trapno);
#endif

View file

@ -0,0 +1,149 @@
# Syntax:
# <thing---->: a field occupying so many bits.
# T: a field occupying one bit.
# .: a bit we don't care about.
# Branch processor instructions.
<18--><LI-------------------->AL branch(0x1f, 0x00, LI, A, L);
<16--><BO-><BI-><BD---------->AL branch(BO, BI, BD, A, L);
<19--><BO-><BI-><BH-><16------>L branch(BO, BI, cpu.lr, 1, L);
<19--><BO-><BI-><BH-><528----->L branch(BO, BI, cpu.ctr, 1, L);
<17-->..............<LEV-->...1. system_call(LEV);
# Condition register instructions.
<19--><BT-><BA-><BB-><257----->. setcr(BT, getcr(BA) & getcr(BB));
<19--><BT-><BA-><BB-><449----->. setcr(BT, getcr(BA) | getcr(BB));
<19--><BT-><BA-><BB-><193----->. setcr(BT, getcr(BA) ^ getcr(BB));
<19--><BT-><BA-><BB-><225----->. setcr(BT, !(getcr(BA) & getcr(BB)));
<19--><BT-><BA-><BB-><33------>. setcr(BT, !(getcr(BA) | getcr(BB)));
<19--><BT-><BA-><BB-><289----->. setcr(BT, getcr(BA) == getcr(BB));
<19--><BT-><BA-><BB-><129----->. setcr(BT, getcr(BA) & !getcr(BB));
<19--><BT-><BA-><BB-><417----->. setcr(BT, getcr(BA) | !getcr(BB));
<19--><BF>.<BA>......<0------->. mcrf(BF, BA);
# Fixed point loads
<34--><RT-><RA-><D-------------> cpu.gpr[RT] = read_byte(reg0(RA) + ext16(D));
<31--><RT-><RA-><RB-><87------>. cpu.gpr[RT] = read_byte(reg0(RA) + reg(RB));
<35--><RT-><RA-><D-------------> uint32_t ea = reg(RA) + ext16(D); cpu.gpr[RT] = read_byte(ea); cpu.gpr[RA] = ea;
<31--><RT-><RA-><RB-><119----->. uint32_t ea = reg(RA) + reg(RB); cpu.gpr[RT] = read_byte(ea); cpu.gpr[RA] = ea;
<40--><RT-><RA-><D-------------> cpu.gpr[RT] = read_word(reg0(RA) + ext16(D));
<31--><RT-><RA-><RB-><279----->. cpu.gpr[RT] = read_word(reg0(RA) + reg(RB));
<41--><RT-><RA-><D-------------> uint32_t ea = reg(RA) + ext16(D); cpu.gpr[RT] = read_word(ea); cpu.gpr[RA] = ea;
<31--><RT-><RA-><RB-><311----->. uint32_t ea = reg(RA) + reg(RB); cpu.gpr[RT] = read_word(ea); cpu.gpr[RA] = ea;
<42--><RT-><RA-><D-------------> cpu.gpr[RT] = ext16(read_word(reg0(RA) + ext16(D)));
<31--><RT-><RA-><RB-><343----->. cpu.gpr[RT] = ext16(read_word(reg0(RA) + reg(RB)));
<43--><RT-><RA-><D-------------> uint32_t ea = reg(RA) + ext16(D); cpu.gpr[RT] = ext16(read_word(ea)); cpu.gpr[RA] = ea;
<31--><RT-><RA-><RB-><375----->. uint32_t ea = reg(RA) + reg(RB); cpu.gpr[RT] = ext16(read_word(ea)); cpu.gpr[RA] = ea;
<32--><RT-><RA-><D-------------> cpu.gpr[RT] = read_long(reg0(RA) + ext16(D));
<31--><RT-><RA-><RB-><23------>. cpu.gpr[RT] = read_long(reg0(RA) + reg(RB));
<33--><RT-><RA-><D-------------> uint32_t ea = reg(RA) + ext16(D); cpu.gpr[RT] = read_long(ea); cpu.gpr[RA] = ea;
<31--><RT-><RA-><RB-><55------>. uint32_t ea = reg(RA) + reg(RB); cpu.gpr[RT] = read_long(ea); cpu.gpr[RA] = ea;
<58--><RT-><RA-><DS---------->10 cpu.gpr[RT] = read_long(reg0(RA) + ext16(DS<<2));
<31--><RT-><RA-><RB-><341----->. cpu.gpr[RT] = read_long(reg0(RA) + reg(RB));
<31--><RT-><RA-><RB-><373----->. uint32_t ea = reg(RA) + reg(RB); cpu.gpr[RT] = read_long(ea); cpu.gpr[RA] = ea;
# Fixed point stores
<38--><RS-><RA-><D-------------> write_byte(reg0(RA) + ext16(D), RS);
<31--><RS-><RA-><RB-><215----->. write_byte(reg0(RA) + reg(RB), RS);
<39--><RS-><RA-><D-------------> uint32_t ea = reg(RA) + ext16(D); write_byte(ea, reg(RS)); cpu.gpr[RA] = ea;
<31--><RS-><RA-><RB-><247----->. uint32_t ea = reg(RA) + reg(RB); write_byte(ea, reg(RS)); cpu.gpr[RA] = ea;
<44--><RS-><RA-><D-------------> write_word(reg0(RA) + ext16(D), RS);
<31--><RS-><RA-><RB-><407----->. write_word(reg0(RA) + reg(RB), RS);
<45--><RS-><RA-><D-------------> uint32_t ea = reg(RA) + ext16(D); write_word(ea, reg(RS)); cpu.gpr[RA] = ea;
<31--><RS-><RA-><RB-><439----->. uint32_t ea = reg(RA) + reg(RB); write_word(ea, reg(RS)); cpu.gpr[RA] = ea;
<36--><RS-><RA-><D-------------> write_long(reg0(RA) + ext16(D), RS);
<31--><RS-><RA-><RB-><151----->. write_long(reg0(RA) + reg(RB), RS);
<37--><RS-><RA-><D-------------> uint32_t ea = reg(RA) + ext16(D); write_long(ea, reg(RS)); cpu.gpr[RA] = ea;
<31--><RS-><RA-><RB-><183----->. uint32_t ea = reg(RA) + reg(RB); write_long(ea, reg(RS)); cpu.gpr[RA] = ea;
# Fixed point load/stores with byte reversal
<31--><RT-><RA-><RB-><790----->. cpu.gpr[RT] = swb16(read_word(reg0(RA) + reg(RB)));
<31--><RT-><RA-><RB-><534----->. cpu.gpr[RT] = swb32(read_long(reg0(RA) + reg(RB)));
<31--><RS-><RA-><RB-><918----->. write_word(reg0(RA) + reg(RB), swb16(reg(RS)));
<31--><RS-><RA-><RB-><662----->. write_long(reg0(RA) + reg(RB), swb32(reg(RS)));
# Load/store multiple
<46--><RT-><RA-><D-------------> read_multiple(reg0(RA) + ext16(D), RT);
<47--><RS-><RA-><D-------------> write_multiple(reg0(RA) + ext16(D), RS);
<31--><RT-><RA-><NB-><597----->. read_string(reg0(RA), RT, NB ? NB : 32);
<31--><RT-><RA-><RB-><533----->. read_string(reg0(RA) + reg(RB), RT, cpu.xer & 0x1f);
<31--><RS-><RA-><NB-><725----->. write_string(reg0(RA), RS, NB ? NB : 32);
<31--><RS-><RA-><RB-><661----->. write_string(reg0(RA) + reg(RB), RS, cpu.xer & 0x1f);
# ALU instructions
<14--><RT-><RA-><SI------------> cpu.gpr[RT] = reg0(RA) + ext16(SI);
<15--><RT-><RA-><SI------------> cpu.gpr[RT] = reg0(RA) + (SI<<16);
<31--><RT-><RA-><RB->O<266---->R setcr0(R, cpu.gpr[RT] = addo(reg(RA), reg(RB), 0, O, 0));
<31--><RT-><RA-><RB->O<40----->R setcr0(R, cpu.gpr[RT] = addo(~reg(RA), reg(RB), 1, O, 0));
<6-->R<RT-><RA-><SI------------> cpu.gpr[RT] = addo(reg(RA), ext16(SI), 0, 0, 1);
<8---><RT-><RA-><SI------------> cpu.gpr[RT] = addo(~reg(RA), ext16(SI), 1, 0, 1);
<31--><RT-><RA-><RB->O<10----->R setcr0(R, cpu.gpr[RT] = addo(reg(RA), reg(RB), 0, O, 1));
<31--><RT-><RA-><RB->O<8------>R setcr0(R, cpu.gpr[RT] = addo(~reg(RA), reg(RB), 1, O, 1));
<31--><RT-><RA-><RB->O<138---->R setcr0(R, cpu.gpr[RT] = addo(reg(RA), reg(RB), carry(), O, 1));
<31--><RT-><RA-><RB->O<136---->R setcr0(R, cpu.gpr[RT] = addo(~reg(RA), reg(RB), carry(), O, 1));
<31--><RT-><RA->.....O<234---->R setcr0(R, cpu.gpr[RT] = addo(reg(RA), -1, carry(), O, 1));
<31--><RT-><RA->.....O<232---->R setcr0(R, cpu.gpr[RT] = addo(~reg(RA), -1, carry(), O, 1));
<31--><RT-><RA->.....O<202---->R setcr0(R, cpu.gpr[RT] = addo(reg(RA), 0, carry(), O, 1));
<31--><RT-><RA->.....O<200---->R setcr0(R, cpu.gpr[RT] = addo(~reg(RA), 0, carry(), O, 1));
<31--><RT-><RA->.....O<104---->R setcr0(R, cpu.gpr[RT] = addo(~reg(RA), 0, 1, O, 0));
<7---><RT-><RA-><SI------------> cpu.gpr[RT] = reg(RA) * ext16(SI);
<31--><RT-><RA-><RB->O<235---->R setcr0(R, cpu.gpr[RT] = mulo(reg(RA), reg(RB), O));
<31--><RT-><RA-><RB->O<491---->R setcr0(R, cpu.gpr[RT] = divo(reg(RA), reg(RB), O));
<31--><RT-><RA-><RB->O<459---->R setcr0(R, cpu.gpr[RT] = divuo(reg(RA), reg(RB), O));
# Comparison instructions
<11--><F>.0<RA-><SI------------> compares(reg(RA), ext16(SI), F);
<31--><F>.0<RA-><RB-><0------->. compares(reg(RA), reg(RB), F);
<10--><F>.0<RA-><UI------------> compareu(reg(RA), UI, F);
<31--><F>.0<RA-><RB-><32------>. compareu(reg(RA), reg(RB), F);
# Logical instructions
<28--><RS-><RA-><UI------------> cpu.gpr[RA] = reg(RS) & UI;
<29--><RS-><RA-><UI------------> cpu.gpr[RA] = reg(RS) & (UI<<16);
<24--><RS-><RA-><UI------------> cpu.gpr[RA] = reg(RS) | UI;
<25--><RS-><RA-><UI------------> cpu.gpr[RA] = reg(RS) | (UI<<16);
<26--><RS-><RA-><UI------------> cpu.gpr[RA] = reg(RS) ^ UI;
<27--><RS-><RA-><UI------------> cpu.gpr[RA] = reg(RS) ^ (UI<<16);
<31--><RS-><RA-><RB-><28------>R setcr0(R, cpu.gpr[RA] = reg(RS) & reg(RB));
<31--><RS-><RA-><RB-><444----->R setcr0(R, cpu.gpr[RA] = reg(RS) | reg(RB));
<31--><RS-><RA-><RB-><316----->R setcr0(R, cpu.gpr[RA] = reg(RS) ^ reg(RB));
<31--><RS-><RA-><RB-><476----->R setcr0(R, cpu.gpr[RA] = ~(reg(RS) & reg(RB)));
<31--><RS-><RA-><RB-><124----->R setcr0(R, cpu.gpr[RA] = ~(reg(RS) | reg(RB)));
<31--><RS-><RA-><RB-><284----->R setcr0(R, cpu.gpr[RA] = ~(reg(RS) ^ reg(RB)));
<31--><RS-><RA-><RB-><60------>R setcr0(R, cpu.gpr[RA] = reg(RS) & ~reg(RB));
<31--><RS-><RA-><RB-><412----->R setcr0(R, cpu.gpr[RA] = reg(RS) | ~reg(RB));
<31--><RS-><RA->.....<954----->R setcr0(R, cpu.gpr[RA] = ext8(reg(RS)));
<31--><RS-><RA->.....<922----->R setcr0(R, cpu.gpr[RA] = ext16(reg(RS)));
<31--><RS-><RA->.....<26------>R setcr0(R, cpu.gpr[RA] = cntlzw(reg(RS)));
<31--><RS-><RA->.....<122----->R setcr0(R, cpu.gpr[RA] = popcntb(reg(RS)));
# Rotation/shift instructions
<21--><RS-><RA-><SH-><MB-><ME->R setcr0(R, cpu.gpr[RA] = rlwnm(reg(RS), SH, MB, ME));
<23--><RS-><RA-><RB-><MB-><ME->R setcr0(R, cpu.gpr[RA] = rlwnm(reg(RS), reg(RB), MB, ME));
<20--><RS-><RA-><SH-><MB-><ME->R setcr0(R, cpu.gpr[RA] = rlwmi(reg(RS), SH, MB, ME));
<31--><RS-><RA-><RB-><24------>R setcr0(R, cpu.gpr[RA] = reg(RS) << (reg(RB) & 0x1f));
<31--><RS-><RA-><RB-><536----->R setcr0(R, cpu.gpr[RA] = reg(RS) >> (reg(RB) & 0x1f));
<31--><RS-><RA-><SH-><824----->R setcr0(R, cpu.gpr[RA] = ((int32_t)reg(RS)) >> SH);
<31--><RS-><RA-><RB-><792----->R setcr0(R, cpu.gpr[RA] = ((int32_t)reg(RS)) >> (reg(RB) & 0x1f));
# Move to/from special registers
<31--><RS-><1-->00000<467----->. cpu.xer = reg(RS);
<31--><RS-><8-->00000<467----->. cpu.lr = reg(RS);
<31--><RS-><9-->00000<467----->. cpu.ctr = reg(RS);
<31--><RT-><1-->00000<339----->. cpu.gpr[RT] = cpu.xer;
<31--><RT-><8-->00000<339----->. cpu.gpr[RT] = cpu.lr;
<31--><RT-><9-->00000<339----->. cpu.gpr[RT] = cpu.ctr;
<31--><RS->0<FXM--->.<144----->. mtcrf(FXM, reg(RS));
<31--><RT->0.........<19------>. cpu.gpr[RT] = cpu.cr;

173
plat/linuxppc/emu/main.c Executable file
View file

@ -0,0 +1,173 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include "emu.h"
#define RAM_BASE 0x10000000
#define RAM_TOP 0x10100000
#define BRK_TOP (RAM_TOP - 0x1000)
#define INIT_SP RAM_TOP
#define INIT_PC 0x08000054
/* Read/write macros */
#define READ_BYTE(BASE, ADDR) (BASE)[ADDR]
#define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) | \
(BASE)[(ADDR)+1])
#define READ_LONG(BASE, ADDR) (((BASE)[ADDR]<<24) | \
((BASE)[(ADDR)+1]<<16) | \
((BASE)[(ADDR)+2]<<8) | \
(BASE)[(ADDR)+3])
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[ADDR] = (VAL)&0xff
#define WRITE_WORD(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>8) & 0xff; \
(BASE)[(ADDR)+1] = (VAL)&0xff
#define WRITE_LONG(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>24) & 0xff; \
(BASE)[(ADDR)+1] = ((VAL)>>16)&0xff; \
(BASE)[(ADDR)+2] = ((VAL)>>8)&0xff; \
(BASE)[(ADDR)+3] = (VAL)&0xff
static void emulated_syscall(void);
static unsigned char ram[RAM_TOP - RAM_BASE];
uint32_t brkbase = RAM_BASE;
uint32_t brkpos = RAM_BASE;
uint32_t entrypoint = RAM_BASE;
void fatal(char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "fatal: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(EXIT_FAILURE);
}
static uint32_t transform_address(uint32_t address)
{
uint32_t a = address - RAM_BASE;
if (a >= RAM_TOP)
fatal("address 0x%x out of bounds", address);
return a;
}
uint32_t read_long(uint32_t address)
{
return READ_LONG(ram, transform_address(address));
}
uint32_t read_word(uint32_t address)
{
return READ_WORD(ram, transform_address(address));
}
uint32_t read_byte(uint32_t address)
{
return READ_BYTE(ram, transform_address(address));
}
void write_byte(uint32_t address, uint32_t value)
{
WRITE_BYTE(ram, transform_address(address), value);
}
void write_word(uint32_t address, uint32_t value)
{
WRITE_WORD(ram, transform_address(address), value);
}
void write_long(uint32_t address, uint32_t value)
{
WRITE_LONG(ram, transform_address(address), value);
}
void system_call(uint8_t trapno)
{
fatal("syscalls unimplemented");
}
static void load_program(FILE* fd)
{
fseek(fd, 0, SEEK_SET);
if (fread(ram, 1, 0x34, fd) != 0x34)
fatal("couldn't read ELF header");
uint32_t phoff = READ_LONG(ram, 0x1c);
uint16_t phentsize = READ_WORD(ram, 0x2a);
uint16_t phnum = READ_WORD(ram, 0x2c);
entrypoint = READ_LONG(ram, 0x18);
if ((phentsize != 0x20) || (phnum != 1))
fatal("unsupported ELF file");
fseek(fd, phoff, SEEK_SET);
if (fread(ram, 1, phentsize, fd) != phentsize)
fatal("couldn't read program header");
uint32_t offset = READ_LONG(ram, 0x04);
uint32_t vaddr = READ_LONG(ram, 0x08);
uint32_t filesz = READ_LONG(ram, 0x10);
uint32_t memsz = READ_LONG(ram, 0x14);
brkbase = brkpos = vaddr + memsz;
uint32_t vaddroffset = transform_address(vaddr);
transform_address(vaddr + memsz); /* bounds check */
memset(ram+vaddroffset, 0, memsz);
fseek(fd, offset, SEEK_SET);
if (fread(ram+vaddroffset, 1, filesz, fd) != filesz)
fatal("couldn't read program data");
}
/* The main loop */
int main(int argc, char* argv[])
{
if(argc != 2)
fatal("syntax: emuppc <program file>");
FILE* fd = fopen(argv[1], "rb");
if (!fd)
fatal("Unable to open %s", argv[1]);
load_program(fd);
fclose(fd);
/* On entry, the Linux stack looks like this.
*
* sp+.. NULL
* sp+8+(4*argc) env (X quads)
* sp+4+(4*argc) NULL
* sp+4 argv (argc quads)
* sp argc
*
* We'll set it up with a bodgy stack frame with argc=0 just to keep the
* startup code happy.
*/
{
uint32_t sp = INIT_SP;
write_long(sp -= 4, 0);
uint32_t envp = sp;
write_long(sp -= 4, envp);
write_long(sp -= 4, 0);
unsigned long argv = sp;
write_long(sp -= 4, argv);
write_long(sp -= 4, 0);
cpu.gpr[1] = sp;
cpu.cia = entrypoint;
}
fatal("execution unimplemented");
return 0;
}

View file

@ -0,0 +1,77 @@
local function decode(line)
local _, _, bits = line:find("^([^ ]+) ")
if #bits ~= 32 then
error("'"..bits.."' isn't 32 bits long")
end
local fields = {}
local i = 1
while i ~= 33 do
local c = line:sub(i, i)
if c ~= "." then
local f = { pos=i }
if c:find("%w") then
f.size = 1
f.value = c
elseif c == "<" then
local _, newi, name = line:find("^<%-*(%w+)%-*>", i)
f.size = 1 + newi - i
f.value = name
i = newi
else
error("bad field char '"..c.."' in '"..line.."'")
end
if f.value:find("[0-9]+") then
f.literal = true
f.variable = false
else
f.literal = false
f.variable = true
end
-- Convert from PowerPC numbering to sane numbering
f.pos = 33-(f.pos + f.size)
fields[#fields+1] = f
end
i = i + 1
end
return fields
end
local function emit(fields, code)
local mask = 0
local value = 0
for _, f in ipairs(fields) do
if f.literal then
local s = math.pow(2, f.pos)
local m = math.pow(2, f.size) - 1
mask = mask + m*s
value = value + f.value*s
end
end
print(string.format("if ((value & 0x%x) == 0x%x) {", mask, value))
for _, f in ipairs(fields) do
if f.variable then
local m = math.pow(2, f.size) - 1
print(string.format("uint32_t %s = (value >> %d) & 0x%x;", f.value, f.pos, m))
end
end
print(code)
print("return;")
print("}")
end
while true do
local line = io.stdin:read("*l")
if not line then
break
end
line = line:gsub("#.*$", "")
line = line:gsub(" *$", "")
if line ~= "" then
local fields = decode(line)
emit(fields, line:sub(34, #line))
end
end

View file

@ -3,5 +3,5 @@ include("tests/plat/build.lua")
plat_testsuite {
name = "tests",
plat = "linuxppc",
method = "qemu-ppc"
method = "plat/linuxppc/emu+emuppc"
}