Skip to content
Browse files

tools/asm: PFPU assembler

  • Loading branch information...
1 parent 9f8e947 commit 8696dfc3739e18f7703732e029f90c1633da4f5f @wpwrak wpwrak committed Jan 15, 2012
Showing with 514 additions and 0 deletions.
  1. +65 −0 tools/asm/Makefile
  2. +68 −0 tools/asm/asm.l
  3. +156 −0 tools/asm/asm.y
  4. +153 −0 tools/asm/pfpuasm.c
  5. +72 −0 tools/asm/pfpuasm.h
View
65 tools/asm/Makefile
@@ -0,0 +1,65 @@
+#
+# Makefile - Makefile of pfpuasm
+#
+# Copyright 2012 by Werner Almesberger
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+
+CFLAGS = -g -Wall -I../../software/include
+SLOPPY = -Wno-unused -Wno-implicit-function-declaration
+LDLIBS = -lfl
+OBJS = pfpuasm.o lex.yy.o y.tab.o
+
+YACC = bison -y
+YYFLAGS = -v
+
+CC_normal := $(CC)
+YACC_normal := $(YACC)
+LEX_normal := $(LEX)
+DEPEND_normal := $(CPP) $(CFLAGS) -MM -MG
+
+CC_quiet = @echo " CC " $@ && $(CC_normal)
+YACC_quiet = @echo " YACC " $@ && $(YACC_normal)
+LEX_quiet = @echo " LEX " $@ && $(LEX_normal)
+GEN_quiet = @echo " GENERATE " $@ &&
+DEPEND_quiet = @$(DEPEND_normal)
+
+ifeq ($(V),1)
+ CC = $(CC_normal)
+ LEX = $(LEX_normal)
+ YACC = $(YACC_normal)
+ GEN =
+ DEPEND = $(DEPEND_normal)
+else
+ CC = $(CC_quiet)
+ LEX = $(LEX_quiet)
+ YACC = $(YACC_quiet)
+ GEN = $(GEN_quiet)
+ DEPEND = $(DEPEND_quiet)
+endif
+
+.PHONY: all clean
+
+all: pfpuasm
+
+pfpuasm: $(OBJS)
+
+lex.yy.c: asm.l y.tab.h
+ $(LEX) asm.l
+
+lex.yy.o: lex.yy.c y.tab.h
+ $(CC) -c $(CFLAGS) $(SLOPPY) lex.yy.c
+
+y.tab.c y.tab.h: asm.y
+ $(YACC) $(YYFLAGS) -d asm.y
+
+y.tab.o: y.tab.c
+ $(CC) -c $(CFLAGS) $(SLOPPY) y.tab.c
+
+clean:
+ rm -f $(OBJS)
+ rm -f lex.yy.c y.tab.c y.tab.h
View
68 tools/asm/asm.l
@@ -0,0 +1,68 @@
+%{
+/*
+ * asm.l - PFPU assembler
+ *
+ * Copyright 2012 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "pfpuasm.h"
+
+#include "y.tab.h"
+
+
+static int lineno = 1;
+
+%}
+
+%%
+
+NOP|nop return TOK_NOP;
+FADD|fadd return TOK_FADD;
+FSUB|fsub return TOK_FSUB;
+FMUL|fmul return TOK_FMUL;
+FABS|fabs return TOK_FABS;
+F2I|f2i return TOK_F2I;
+I2F|i2f return TOK_I2F;
+VECTOUT|vectout return TOK_VECTOUT;
+SIN|sin return TOK_SIN;
+COS|cos return TOK_COS;
+ABOVE|above return TOK_ABOVE;
+EQUAL|equal return TOK_EQUAL;
+COPY|copy return TOK_COPY;
+IF|if return TOK_IF;
+TSIGN|tsign return TOK_TSIGN;
+QUAKE|quake return TOK_QUAKE;
+
+[Rr][0-9]+ { yylval.reg = atoi(yytext+1);
+ return REG; }
+
+"->" return ARROW;
+
+[0-9]+"."?[0-9]*|"."[0-9]+ { yylval.f = atof(yytext);
+ return FLOAT; }
+0[Xx][0-9a-fA-F]+ { yylval.i = strtoul(yytext, NULL, 0);
+ return HEX; }
+
+[ \t] ;
+\n lineno++;
+
+^#\ [0-9]+\ \"[^"]*\"(\ [0-9]+)*\n {
+ lineno = strtol(yytext+2, NULL, 0); }
+
+. return *yytext;
+
+%%
+
+void yyerror(const char *s)
+{
+ fprintf(stderr, "%d: %s\n", lineno, s);
+ exit(1);
+}
View
156 tools/asm/asm.y
@@ -0,0 +1,156 @@
+%{
+/*
+ * asm.y - PFPU assembler
+ *
+ * Copyright 2012 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdint.h>
+
+#include "hw/pfpu.h"
+
+#include "pfpuasm.h"
+
+#include "y.tab.h"
+
+
+#define UNARY(op, opa, dest) \
+ emit(PFPU_OPCODE_##op, opa, 0, dest, PFPU_LATENCY_##op)
+#define BINARY(op, opa, opb, dest) \
+ emit(PFPU_OPCODE_##op, opa, opb, dest, PFPU_LATENCY_##op)
+
+
+static void emit(int opcode, int opa, int opb, int dest, int latency)
+{
+ *pc++ |= opcode << OPCODE_SHIFT | opb << OPB_SHIFT | opa << OPA_SHIFT;
+
+ if (dest <= 0)
+ return;
+
+ if (pc[latency-1] & (DEST_MASK << DEST_SHIFT))
+ yyerror("destination conflict");
+ pc[latency-1] |= dest << DEST_SHIFT;
+}
+
+%}
+
+%union {
+ float f;
+ uint32_t i;
+ int reg;
+};
+
+%token TOK_NOP TOK_FADD TOK_FSUB TOK_FMUL TOK_FABS
+%token TOK_F2I TOK_I2F TOK_VECTOUT TOK_SIN TOK_COS
+%token TOK_ABOVE TOK_EQUAL TOK_COPY TOK_IF TOK_TSIGN TOK_QUAKE
+
+%token ARROW
+
+%token <f> FLOAT
+%token <i> HEX
+%token <reg> REG
+
+%type <i> value
+
+%%
+
+all:
+ regs ops;
+
+regs:
+ | reg regs;
+
+reg:
+ REG '=' value
+ {
+ regs[$1] = $3;
+ if ($1 > max_reg)
+ max_reg = $1;
+ }
+ ;
+
+value:
+ HEX
+ {
+ $$ = $1;
+ }
+ | FLOAT
+ {
+ $$ = f2i($1);
+ }
+ ;
+
+ops:
+ | op ops;
+
+op:
+ TOK_NOP
+ {
+ emit(PFPU_OPCODE_NOP, 0, 0, 0, -1);
+ }
+ | TOK_FADD REG ',' REG ARROW REG
+ {
+ BINARY(FADD, $2, $4, $6);
+ }
+ | TOK_FSUB REG ',' REG ARROW REG
+ {
+ BINARY(FSUB, $2, $4, $6);
+ }
+ | TOK_FMUL REG ',' REG ARROW REG
+ {
+ BINARY(FMUL, $2, $4, $6);
+ }
+ | TOK_FABS REG ARROW REG
+ {
+ UNARY(FABS, $2, $4);
+ }
+ | TOK_F2I REG ARROW REG
+ {
+ UNARY(F2I, $2, $4);
+ }
+ | TOK_I2F REG ARROW REG
+ {
+ UNARY(I2F, $2, $4);
+ }
+ | TOK_VECTOUT REG ',' REG ARROW REG
+ {
+ BINARY(VECTOUT, $2, $4, $6);
+ }
+ | TOK_SIN REG ARROW REG
+ {
+ UNARY(SIN, $2, $4);
+ }
+ | TOK_COS REG ARROW REG
+ {
+ UNARY(COS, $2, $4);
+ }
+ | TOK_ABOVE REG ',' REG ARROW REG
+ {
+ BINARY(ABOVE, $2, $4, $6);
+ }
+ | TOK_EQUAL REG ',' REG ARROW REG
+ {
+ BINARY(EQUAL, $2, $4, $6);
+ }
+ | TOK_COPY REG ARROW REG
+ {
+ UNARY(COPY, $2, $4);
+ }
+ | TOK_IF REG ',' REG ARROW REG
+ {
+ BINARY(IF, $2, $4, $6);
+ }
+ | TOK_TSIGN REG ',' REG ARROW REG
+ {
+ BINARY(TSIGN, $2, $4, $6);
+ }
+ | TOK_QUAKE REG ',' REG ARROW REG
+ {
+ BINARY(QUAKE, $2, $4, $6);
+ }
+ ;
View
153 tools/asm/pfpuasm.c
@@ -0,0 +1,153 @@
+/*
+ * pfpuasm.c - PFPU assembler
+ *
+ * Copyright 2012 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "hw/pfpu.h"
+
+#include "pfpuasm.h"
+
+
+#define CPP "cpp"
+
+
+uint32_t prog[PFPU_PROGSIZE];
+uint32_t *pc = prog;
+
+uint32_t regs[PFPU_REG_COUNT];
+int max_reg = 0;
+
+
+int yyparse(void);
+
+
+static pid_t pid = 0;
+
+
+static void kill_cpp(void)
+{
+ if (pid)
+ kill(pid, SIGTERM);
+}
+
+
+static void cpp(char *const *argv)
+{
+ int fds[2];
+
+ if (pipe(fds) < 0) {
+ perror("pipe");
+ exit(1);
+ }
+ pid = fork();
+ if (pid < 0) {
+ perror("fork");
+ exit(1);
+ }
+ if (!pid) {
+ close(fds[0]);
+ if (dup2(fds[1], 1) < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ execvp(CPP, argv);
+ perror(CPP);
+ exit(1);
+ }
+ close(fds[1]);
+ if (dup2(fds[0], 0) < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ atexit(kill_cpp);
+}
+
+
+#define ATTR(op, ar) \
+ [PFPU_OPCODE_##op] = { \
+ .name = #op, \
+ .latency = PFPU_LATENCY_##op, \
+ .arity = ar \
+ }
+
+#define PFPU_LATENCY_NOP 0 /* fake */
+
+static struct attr {
+ const char *name;
+ int latency;
+ int arity;
+} attrs[16] = {
+ ATTR(NOP, 0),
+ ATTR(FADD, 2),
+ ATTR(FSUB, 2),
+ ATTR(FMUL, 2),
+ ATTR(FABS, 1),
+ ATTR(F2I, 1),
+ ATTR(I2F, 1),
+ ATTR(VECTOUT, 2),
+ ATTR(SIN, 1),
+ ATTR(COS, 1),
+ ATTR(ABOVE, 2),
+ ATTR(EQUAL, 2),
+ ATTR(COPY, 2),
+ ATTR(IF, 2),
+ ATTR(TSIGN, 2),
+ ATTR(QUAKE, 2),
+};
+
+
+int main(int argc, char *const *argv)
+{
+ const uint32_t *p;
+ const uint32_t *r;
+
+ cpp(argv);
+ (void) yyparse();
+
+ for (r = regs+PFPU_SPREG_COUNT; r <= regs+max_reg; r++)
+ printf("0x%08x\t# R%u = %f\n",
+ *r, (unsigned) (r-regs), i2f(*r));
+ for (p = prog; p != pc; p++) {
+ int opcode = (*p >> OPCODE_SHIFT) & OPCODE_MASK;
+ int opa = (*p >> OPA_SHIFT) & OPA_MASK;
+ int opb = (*p >> OPB_SHIFT) & OPB_MASK;
+ int dest;
+ const struct attr *attr = attrs+opcode;
+
+ printf("%08x\t# %3u: %s", *p, (unsigned) (p-prog), attr->name);
+ switch (attr->arity) {
+ case 0:
+ break;
+ case 1:
+ printf("\tR%d", opa);
+ break;
+ case 2:
+ printf("\tR%d, R%d", opa, opb);
+ break;
+ default:
+ abort();
+ }
+ if (attr->latency) {
+ dest = (p[attr->latency] >> DEST_SHIFT) & DEST_MASK;
+ printf(" -> R%d @ %u",
+ dest, (unsigned) (p-prog)+attr->latency);
+ }
+ dest = (*p >> DEST_SHIFT) & DEST_MASK;
+ if (dest)
+ printf("\t\tdest R%d", dest);
+ putchar('\n');
+ }
+ return 0;
+}
View
72 tools/asm/pfpuasm.h
@@ -0,0 +1,72 @@
+/*
+ * pfpuasm.h - PFPU assembler
+ *
+ * Copyright 2012 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef PFPUASM_H
+#define PFPUASM_H
+
+#include <stdint.h>
+
+#include "hw/pfpu.h"
+
+
+/*
+ * We can't use a union for portability reasons. Safer to compose the
+ * instruction "manually".
+ *
+ * Instruction format:
+ *
+ * 3 3 2 2 2 2 2|2 2 2 2 2 1 1|1 1 1 1 1 1 1|1 |
+ * 1 0 9 8 7 6 5|4 3 2 1 0 9 8|7 6 5 4 3 2 1|0 9 8 7|6 5 4 3 2 1 0
+ * pad | opa | opb |opcode | dest
+ */
+
+#define OPA_SHIFT 18
+#define OPA_MASK 0x7f
+#define OPB_SHIFT 11
+#define OPB_MASK 0x7f
+#define OPCODE_SHIFT 7
+#define OPCODE_MASK 0x0f
+#define DEST_SHIFT 0
+#define DEST_MASK 0x7f
+
+
+extern uint32_t prog[PFPU_PROGSIZE];
+extern uint32_t *pc;
+
+extern uint32_t regs[PFPU_REG_COUNT];
+extern int max_reg;
+
+
+union u_f2i {
+ float f;
+ int i;
+};
+
+
+static inline uint32_t f2i(float f)
+{
+ union u_f2i u = { .f = f };
+
+ return u.i;
+}
+
+
+static inline float i2f(uint32_t i)
+{
+ union u_f2i u = { .i = i };
+
+ return u.f;
+}
+
+
+void yyerror(const char *s);
+
+#endif /* !PFPUASM_H */

0 comments on commit 8696dfc

Please sign in to comment.
Something went wrong with that request. Please try again.