Skip to content

Commit

Permalink
Add fpu support, somewhat working poll, separate tests into new proje…
Browse files Browse the repository at this point in the history
…ct, \r\n, jeez I need to commit more often
  • Loading branch information
tbodt committed Aug 28, 2017
1 parent 9dbaeee commit ea65057
Show file tree
Hide file tree
Showing 28 changed files with 271 additions and 110 deletions.
20 changes: 13 additions & 7 deletions debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#ifndef DEBUG_instr
#define DEBUG_instr DEBUG_all
#endif
#ifndef DEBUG_debug
#define DEBUG_debug DEBUG_all
#endif

#if DEBUG_default
#define TRACE_default TRACE__
Expand All @@ -28,20 +31,23 @@
#else
#define TRACE_instr TRACE__NOP
#endif
#if DEBUG_debug
#define TRACE_debug TRACE__
#else
#define TRACE_debug TRACE__NOP
#endif

#define TRACE__NOP(msg, ...) do {} while(0)
#define TRACE__(msg, ...) println(msg, ##__VA_ARGS__)
#define TRACE__(msg, ...) printf(msg, ##__VA_ARGS__)
#define TRACE_(chan, msg, ...) CONCAT(TRACE_, chan)(msg, ##__VA_ARGS__)
#define TRACE(msg, ...) TRACE_(DEFAULT_CHANNEL, msg, ##__VA_ARGS__)
#define TRACELN_(chan, msg, ...) TRACE_(chan, msg "\r\n", ##__VA_ARGS__)
#define TRACELN(msg, ...) TRACE(msg "\r\n", ##__VA_ARGS__)
#ifndef DEFAULT_CHANNEL
#define DEFAULT_CHANNEL default
#endif

#define TODO(msg, ...) { println("TODO: " msg, ##__VA_ARGS__); abort(); }
#define FIXME(msg, ...) println("FIXME " msg, ##__VA_ARGS__)
#define DIE(msg) { perror(msg); abort(); }

#if defined(__i386__) || defined(__x86_64__)
#define debugger __asm__("int3")
#elif defined(__arm__)
#define debugger __asm__("trap")
#endif

5 changes: 5 additions & 0 deletions emu/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define EMU_H

#include <stddef.h>
#include <softfloat.h>
#include "misc.h"
#include "emu/memory.h"

Expand Down Expand Up @@ -79,6 +80,10 @@ struct cpu_state {
bits of_ops:1;
bits af_ops:1;

// fpu
extFloat80_t fp[8];
unsigned top:3;

// See comment in sys/tls.c
addr_t tls_ptr;

Expand Down
54 changes: 47 additions & 7 deletions emu/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,15 +364,15 @@ int CONCAT(decoder_name, OP_SIZE)(struct cpu_state *cpu) {
case 0x5e: TRACEI("pop osi"); POP(osi); break;
case 0x5f: TRACEI("pop odi"); POP(odi); break;

case 0x65: TRACE("segment gs\n");
case 0x65: TRACELN("segment gs");
addr += cpu->tls_ptr; goto restart;

case 0x66:
#if OP_SIZE == 32
TRACE("entering 16 bit mode\n");
TRACELN("entering 16 bit mode");
return cpu_step16(cpu);
#else
TRACE("entering 32 bit mode\n");
TRACELN("entering 32 bit mode");
return cpu_step32(cpu);
#endif

Expand Down Expand Up @@ -592,6 +592,35 @@ int CONCAT(decoder_name, OP_SIZE)(struct cpu_state *cpu) {

#undef GRP2

case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
TRACEI("fpu\t\t"); READMODRM;
if (modrm.type != mod_reg) {
switch (insn << 4 | modrm.opcode) {
case 0xd81: TRACE("fmul mem32"); FMUL(mem_addr_real,32); break;
case 0xda4: TRACE("fisub mem32"); FISUB(mem_addr,32); break;
case 0xdc0: TRACE("fadd mem64"); FADDM(mem_addr_real,64); break;
case 0xdd0: TRACE("fld mem64"); FLD(mem_addr_real,64); break;
case 0xdd2: TRACE("fst mem64"); FSTM(mem_addr_real,64); break;
case 0xdd3: TRACE("fstp mem64"); FSTM(mem_addr_real,64); FPOP; break;
case 0xdf5: TRACE("fild mem64"); FILD(mem_addr,64); break;
default: TRACE("undefined"); UNDEFINED;
}
} else {
switch (insn << 4 | modrm.opcode) {
case 0xd95:
switch (modrm.rm_opcode) {
case 6: TRACE("fldz"); FLDC(zero); break;
default: TRACE("undefined"); UNDEFINED;
}
break;
case 0xdb5: TRACE("fucomi st"); FUCOMI(); break;
case 0xdd3: TRACE("fstp st"); FST(); FPOP; break;
case 0xdf5: TRACE("fucomip st"); FUCOMI(); FPOP; break;
default: TRACE("undefined"); UNDEFINED;
}
}
break;

case 0xe3: TRACEI("jcxz rel8\t");
READIMM8; JCXZ_REL(imm8); break;

Expand All @@ -603,12 +632,22 @@ int CONCAT(decoder_name, OP_SIZE)(struct cpu_state *cpu) {
case 0xeb: TRACEI("jmp rel8\t");
READIMM8; JMP_REL(imm8); break;

case 0xf0: TRACE("lock (ignored for now)\n"); goto restart;
case 0xf0: TRACELN("lock (ignored for now)"); goto restart;

case 0xf2:
READINSN;
switch (insn) {
case 0x0f:
READINSN;
switch (insn) {
case 0x2c: TRACEI("cvttsd2si modrm64, reg32");
READMODRM; if (modrm.type == mod_reg) UNDEFINED; // TODO xmm
CVTTSD2SI(mem_addr_real, modrm_reg); break;
default: TRACE("undefined"); UNDEFINED;
}
break;
case 0xae: TRACEI("repnz scasb"); REPNZ(SCAS(8)); break;
default: TRACE("undefined"); UNDEFINED;
}
break;

Expand All @@ -622,6 +661,7 @@ int CONCAT(decoder_name, OP_SIZE)(struct cpu_state *cpu) {
switch (insn) {
case 0x7e: TRACEI("movq modrm, xmm");
READMODRM; MOVQ(modrm_val, modrm_reg); break;
default: TRACE("undefined"); UNDEFINED;
}
break;

Expand All @@ -638,7 +678,7 @@ int CONCAT(decoder_name, OP_SIZE)(struct cpu_state *cpu) {
// ret. gcc used to use nop ret but repz ret is only one
// instruction
case 0xc3: TRACEI("repz ret\t"); RET_NEAR(); break;
default: TRACE("undefined\n"); UNDEFINED;
default: TRACELN("undefined"); UNDEFINED;
}
break;

Expand Down Expand Up @@ -697,9 +737,9 @@ int CONCAT(decoder_name, OP_SIZE)(struct cpu_state *cpu) {
#undef GRP5

default:
TRACE("undefined\n");
TRACELN("undefined");
UNDEFINED;
}
TRACE("\n");
TRACELN("");
return -1; // everything is ok.
}
1 change: 1 addition & 0 deletions emu/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@
#define CLD cpu->df = 0

#include "emu/interp/sse.h"
#include "emu/interp/fpu.h"

// ok now include the decoding function
#define decoder_name cpu_step
Expand Down
48 changes: 48 additions & 0 deletions emu/interp/fpu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include <softfloat.h>

#define ty_real(x) ty_real_##x
#define ty_real_16 float16_t
#define ty_real_32 float32_t
#define ty_real_64 float64_t
#define ty_real_80 extFloat80_t

#define mem_read_real(addr, size) mem_read_type(addr, ty_real(size))
#define mem_write_real(addr, val, size) mem_write_type(addr, val, ty_real(size))
#define get_mem_addr_real(size) mem_read_real(addr, size)
#define set_mem_addr_real(to, size) mem_write_real(addr, to, size)

#define extF80_to_f(f, z) CONCAT(extF80_to_f, sz(z))(f)
#define f_to_extF80(f_, z) CONCAT3(f, sz(z), _to_extF80)(f_)

#define ST(i) cpu->fp[cpu->top + i]
#define ST_i ST(modrm.rm_opcode)
#define FPUSH(val) \
cpu->top--; ST(0) = val
#define FPOP \
cpu->top++

#define FADDM(val,z) \
ST(0) = extF80_add(ST(0), f_to_extF80(get(val,z),z))
#define FISUB(val,z) \
ST(0) = extF80_sub(ST(0), i64_to_extF80((sint(z)) get(val,z)))
#define FMUL(val,z) \
ST(0) = extF80_mul(ST(0), f_to_extF80(get(val,z),z))

#define FUCOMI() \
cpu->zf = extF80_eq(ST(0), ST_i); cpu->zf_res = 0; \
cpu->cf = extF80_lt(ST(0), ST_i); cpu->sf_res = 0; \
cpu->pf = 0; cpu->pf_res = 0
// not worrying about nans and shit yet

#define FILD(val,z) \
FPUSH(i64_to_extF80((sint(z)) get(val,z)))
#define FLD(val,z) \
FPUSH(f_to_extF80(get(val,z),z))

#define FLDC(what) FPUSH(fconst_##what)
#define fconst_zero i64_to_extF80(0)

#define FSTM(val,z) \
set(val, extF80_to_f(ST(0),z),z)

#define FST() ST_i = ST(0)
4 changes: 4 additions & 0 deletions emu/interp/sse.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@

#define MOVD(src, dst) \
set(dst, get(src,128).dw[0],32)

#include <softfloat.h>
#define CVTTSD2SI(src, dst) \
set(dst, f64_to_i32(get(src,64), softfloat_round_minMag, false),32)
1 change: 1 addition & 0 deletions emu/modrm.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ static inline struct regptr decode_reg(byte_t reg) {
struct modrm_info modrm_compute_info(byte_t byte) {
struct modrm_info info;
info.opcode = REG(byte);
info.rm_opcode = RM(byte); // for floating point
info.sib = false;
info.reg = decode_reg(REG(byte));
info.modrm_regid = decode_reg(RM(byte));
Expand Down
4 changes: 3 additions & 1 deletion emu/modrm.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef MODRM_H
#define MODRM_H

#include "debug.h"
#include "misc.h"
#include "emu/cpu.h"

Expand Down Expand Up @@ -35,12 +36,13 @@ struct modrm_info {
mod_reg,
} type;
struct regptr modrm_regid;
byte_t rm_opcode;

// REG BITS
// offsets of the register into the cpu_state structure
struct regptr reg;
// for when it's not a register
uint8_t opcode;
byte_t opcode;
};

#ifdef DISABLE_MODRM_TABLE
Expand Down
86 changes: 49 additions & 37 deletions fs/poll.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include <poll.h>
#include "misc.h"
#include "util/list.h"
#include "sys/errno.h"
#include "sys/fs.h"

Expand Down Expand Up @@ -56,57 +58,67 @@ void poll_wake_pollable(struct pollable *pollable) {
lock(fd);
list_for_each_entry(&fd->poll_fds, poll_fd, polls) {
struct poll *poll = poll_fd->poll;
if (poll->notify_pipe[1] != -1) {
write(poll->notify_pipe[1], &poll_fd, sizeof(poll_fd));
}
if (poll->notify_pipe[1] != -1)
write(poll->notify_pipe[1], "", 1);
}
unlock(fd);
}
unlock(pollable);
}

int poll_wait(struct poll *poll_, struct poll_event *event, int timeout) {
int res;
// TODO this is pretty broken with regards to timeouts

lock(poll_);
// make a pipe so things can notify us that things happened
if (pipe(poll_->notify_pipe) < 0)
return err_map(errno);
int pipe_rd = poll_->notify_pipe[0];
while (true) {
// check if any fds are ready
struct poll_fd *poll_fd;
list_for_each_entry(&poll_->poll_fds, poll_fd, fds) {
struct fd *fd = poll_fd->fd;
if (fd->ops->poll(fd) & poll_fd->types) {
event->fd = fd;
event->types = poll_fd->types;
unlock(poll_);
return 1;
}
}

// wait for events on the notify pipe
struct pollfd pollfd;
retry:
pollfd.fd = pipe_rd;
pollfd.events = POLLIN;
unlock(poll_);
int err = poll(&pollfd, 1, timeout);
// TODO it's possible the poll_fd struct got freed while that poll call was
// happening, so check for that or something
lock(poll_);
if (err < 0) {
err = err_map(errno);
goto done;
}
if (err == 0)
goto done;
// wait for a ready notification
if (pipe(poll_->notify_pipe) < 0) {
res = err_map(errno);
break;
}
struct pollfd pollfd;
pollfd.fd = poll_->notify_pipe[0];
pollfd.events = POLLIN;
unlock(poll_);
res = poll(&pollfd, 1, timeout);
lock(poll_);
if (res < 0) {
res = err_map(errno);
break;
}
if (res == 0)
break;

struct poll_fd *poll_fd;
if (read(pipe_rd, &poll_fd, sizeof(poll_fd)) != sizeof(poll_fd)) {
err = err_map(errno);
goto done;
}
char fuck;
if (read(poll_->notify_pipe[0], &fuck, 1) != 1) {
res = err_map(errno);
break;
}

if (!(poll_fd->fd->ops->poll(poll_fd->fd) & poll_fd->types))
goto retry;
close(poll_->notify_pipe[0]);
poll_->notify_pipe[0] = -1;
close(poll_->notify_pipe[1]);
poll_->notify_pipe[1] = -1;
}

event->fd = poll_fd->fd;
event->types = poll_fd->types;
done:
close(poll_->notify_pipe[0]);
close(poll_->notify_pipe[1]);
if (poll_->notify_pipe[0] != -1)
close(poll_->notify_pipe[0]);
if (poll_->notify_pipe[1] != -1)
close(poll_->notify_pipe[1]);
unlock(poll_);
return err;
return res;
}

void poll_destroy(struct poll *poll) {
Expand Down
6 changes: 6 additions & 0 deletions fs/tty-real.c
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
#include "debug.h"
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <signal.h>

#include "sys/calls.h"
#include "fs/tty.h"

static void real_tty_read_thread(struct tty *tty) {
char ch;
while (read(STDIN_FILENO, &ch, 1) == 1) {
if (ch == '\x1c') {
// ^\ (so ^C still works for emulated SIGINT)
raise(SIGINT);
}
tty_input(tty, &ch, 1);
}
}
Expand Down
Loading

0 comments on commit ea65057

Please sign in to comment.