Commit ba691ad8 authored by Koen Martens's avatar Koen Martens

tools: add most recent binutils patches

parent 396c95a3
......@@ -8,8 +8,22 @@ Most of the interesting stuff is in:
doc/ - an attempt at documenting it all
src/ - the source
src/vhdl - vhdl sources
src/asm - programs in gmpu assembly
rc/tools
test/ - testbenches
Tools
-----
Under tools are:
ihex2vhdl/ - a simple python script to conver ihex to vhdl rom
binutils/ - a series of patches to binutils to add gmpu support
If you want to assemble programs to run in the gmpu, you need to
compile binutils. More info is in the binutils/ subdir.
Testcases
---------
......
From 991e2fed168908766ff9b86eca21fd9ff85ba847 Mon Sep 17 00:00:00 2001
From b4edfe8a3cd4611a9bae3fa0886653bb1b4a8b26 Mon Sep 17 00:00:00 2001
From: Koen Martens <kmartens@sonologic.nl>
Date: Fri, 29 May 2015 18:32:33 +0200
Subject: [PATCH 1/2] First skeletal support for gmpu (assemble/disassemble
Subject: [PATCH 01/25] First skeletal support for gmpu (assemble/disassemble
nop).
---
......@@ -166,10 +166,10 @@ index 677c470..615342f 100644
&bfd_h8500_arch,
&bfd_hppa_arch,
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 6f7ae34..c05ec93 100644
index ee67340..189b219 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2298,6 +2298,8 @@ enum bfd_architecture
@@ -2299,6 +2299,8 @@ enum bfd_architecture
#define bfd_mach_nios2 0
bfd_arch_visium, /* Visium */
#define bfd_mach_visium 1
......@@ -698,7 +698,7 @@ index ad060ee..b2d38d9 100644
extern int print_insn_h8300h (bfd_vma, disassemble_info *);
extern int print_insn_h8300s (bfd_vma, disassemble_info *);
diff --git a/include/elf/common.h b/include/elf/common.h
index b087d9c..0a4e41e 100644
index e6d8c14..d83271e 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -410,6 +410,9 @@
......
From 0809d22bf2b6605e1182e6700764459faa0a2fb4 Mon Sep 17 00:00:00 2001
From e384349bfe7623e4353c2f6fe23cacb51756184d Mon Sep 17 00:00:00 2001
From: Koen Martens <kmartens@sonologic.nl>
Date: Sun, 31 May 2015 11:26:43 +0200
Subject: [PATCH 2/2] Add opcode fields and mov instruction definition.
Subject: [PATCH 02/25] Add opcode fields and mov instruction definition.
---
include/opcode/gmpu.h | 4 ++++
......
From b7222de6dc444c63678570257790bf65a627ea93 Mon Sep 17 00:00:00 2001
From: Koen Martens <gmc@sonologic.nl>
Date: Wed, 24 Jun 2015 17:08:59 +0200
Subject: [PATCH 03/25] Add gmpu to top-level configure
---
config.sub | 1 +
configure | 2 ++
2 files changed, 3 insertions(+)
diff --git a/config.sub b/config.sub
index 8f1229c..4caf3ef 100755
--- a/config.sub
+++ b/config.sub
@@ -261,6 +261,7 @@ case $basic_machine in
| d10v | d30v | dlx | dsp16xx \
| e2k | epiphany \
| fido | fr30 | frv | ft32 \
+ | gmpu \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
diff --git a/configure b/configure
index a2e253a..d227105 100755
--- a/configure
+++ b/configure
@@ -3395,6 +3395,8 @@ case "${target}" in
;;
frv-*-*)
;;
+ gmpu-*-*)
+ ;;
hppa*-*-linux*)
;;
hppa*-*-hpux*)
--
1.9.1
From e2c0593c87257300e949bbeb7b8e63c1df1d2fb6 Mon Sep 17 00:00:00 2001
From: Koen Martens <gmc@sonologic.nl>
Date: Wed, 24 Jun 2015 17:10:03 +0200
Subject: [PATCH 04/25] Fix comment in bfd definition.
---
bfd/cpu-gmpu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bfd/cpu-gmpu.c b/bfd/cpu-gmpu.c
index 64e33b4..a7b1af1 100644
--- a/bfd/cpu-gmpu.c
+++ b/bfd/cpu-gmpu.c
@@ -25,7 +25,7 @@
const bfd_arch_info_type bfd_gmpu_arch =
{
- 32, /* 16 bits in a word. */
+ 32, /* 32 bits in a word. */
32, /* 32 bits in an address. */
8, /* 8 bits in a byte. */
bfd_arch_gmpu, /* enum bfd_architecture arch. */
--
1.9.1
From 3dc81ed9aa4a1c07366700552829f791cfbe5921 Mon Sep 17 00:00:00 2001
From: Koen Martens <gmc@sonologic.nl>
Date: Wed, 24 Jun 2015 17:10:39 +0200
Subject: [PATCH 05/25] Make gmpu parser use opcode info table.
---
gas/config/tc-gmpu.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/gas/config/tc-gmpu.c b/gas/config/tc-gmpu.c
index eac3098..af1e725 100644
--- a/gas/config/tc-gmpu.c
+++ b/gas/config/tc-gmpu.c
@@ -1,6 +1,7 @@
#include "as.h"
#include "safe-ctype.h"
#include "opcode/gmpu.h"
+#include <arpa/inet.h>
extern const gmpu_opc_info_t gmpu_opc_info[128];
@@ -59,12 +60,27 @@ md_assemble (char *str)
{
char *to = NULL;
+ unsigned int opcode = 0U;
+ size_t opcode_idx = 0;
+ int valid_opcode = 0;
+
+
str = strip_spaces(str);
- if(!strcmp(str,"nop")) {
- // emit nop opcode
+ while(NULL != gmpu_opc_info[opcode_idx].name) {
+ if(!strcmp(str, gmpu_opc_info[opcode_idx].name)) {
+ opcode = gmpu_opc_info[opcode_idx].bits & gmpu_opc_info[opcode_idx].mask;
+ valid_opcode=1;
+ break;
+ }
+ opcode_idx++;
+ }
+
+ if(valid_opcode) {
+ // emit opcode
to = frag_more(4);
- bzero (to, 4);
+ *((unsigned int *)to)=htonl(opcode);
+ //memcpy(to, &opcode, 4);
} else {
as_bad (_("Unknown instruction '%s'"), str);
}
--
1.9.1
From 56a454a47b216a5d835f4d4879ca55eb44f28465 Mon Sep 17 00:00:00 2001
From: Koen Martens <gmc@sonologic.nl>
Date: Wed, 24 Jun 2015 17:11:06 +0200
Subject: [PATCH 06/25] Add instructions, define registers.
---
include/opcode/gmpu.h | 15 +++++++++++++++
opcodes/gmpu-opc.c | 23 +++++++++++++++++++++--
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/include/opcode/gmpu.h b/include/opcode/gmpu.h
index 7409d41..dcbfbaa 100644
--- a/include/opcode/gmpu.h
+++ b/include/opcode/gmpu.h
@@ -21,6 +21,14 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
#define GMPU_FIELD_SIGNED_BIT 27
#define GMPU_FIELD_SIGNED_SIZE 1
+#define GMPU_FIELD_DSTREG (1<<1)
+#define GMPU_FIELD_DSTREG_BIT 23
+#define GMPU_FIELD_DSTREG_SIZE 4
+
+#define GMPU_FIELD_SRCREG (1<<2)
+#define GMPU_FIELD_SRCREG_BIT 19
+#define GMPU_FIELD_SRCREG_SIZE 4
+
typedef struct gmpu_opc_info_t
{
const char *name;
@@ -30,3 +38,10 @@ typedef struct gmpu_opc_info_t
int fields;
} gmpu_opc_info_t;
+
+typedef struct gmpu_reg_info_t
+{
+ const char *name; /**< register name */
+ int cpu; /**< 0=user, 1=cpu reg */
+ int index; /**< reg index */
+} gmpu_reg_info_t;
diff --git a/opcodes/gmpu-opc.c b/opcodes/gmpu-opc.c
index d17c0d2..87859d9 100644
--- a/opcodes/gmpu-opc.c
+++ b/opcodes/gmpu-opc.c
@@ -26,7 +26,26 @@
const gmpu_opc_info_t gmpu_opc_info[] =
{
-{ "nop", 0, 0xffffffffU, 0x00000000U, 0},
-{ "mov", 0, 0xf0000000U, 0x10000000U, GMPU_FIELD_SIGNED},
+{ "nop", 0, 0xffffffffU, 0x00000000U, 0},
+{ "halt", 0, 0xf0000000U, 0xf0000000U, 0},
+{ "mov", 0, 0xf0000000U, 0x10000000U, GMPU_FIELD_SIGNED},
+{ "add", 0, 0xf0000000U, 0x10000000U, GMPU_FIELD_SIGNED},
+{ "adds", 0, 0xf0000000U, 0x10000000U, GMPU_FIELD_SIGNED},
{ NULL, 0, 0, 0, 0}
};
+
+const gmpu_reg_info_t gmpu_reg_info[] =
+{
+{ "r0", 0, 0 },
+{ "r1", 0, 1 },
+{ "r2", 0, 2 },
+{ "r3", 0, 3 },
+{ "r4", 0, 4 },
+{ "r5", 0, 5 },
+{ "r6", 0, 6 },
+{ "r7", 0, 7 },
+{ "ip", 1, 8 },
+{ "sp", 1, 9 },
+{ "sr", 1, 10 },
+};
+
--
1.9.1
From 0dee4317273658f77b48a75b71a2642b5ff89423 Mon Sep 17 00:00:00 2001
From: Koen Martens <gmc@sonologic.nl>
Date: Wed, 24 Jun 2015 19:10:03 +0200
Subject: [PATCH 07/25] gmpu: parse instruction and operands, assemble opcode
---
gas/config/tc-gmpu.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++--
include/opcode/gmpu.h | 7 ++
opcodes/gmpu-opc.c | 13 ++--
3 files changed, 197 insertions(+), 11 deletions(-)
diff --git a/gas/config/tc-gmpu.c b/gas/config/tc-gmpu.c
index af1e725..29dd774 100644
--- a/gas/config/tc-gmpu.c
+++ b/gas/config/tc-gmpu.c
@@ -4,6 +4,7 @@
#include <arpa/inet.h>
extern const gmpu_opc_info_t gmpu_opc_info[128];
+extern const gmpu_reg_info_t gmpu_reg_info[128];
const char *md_shortopts = "";
@@ -55,6 +56,102 @@ strip_spaces(char *str)
return str;
}
+static int
+gmpu_parse_register(const char *str)
+{
+ int i=0;
+
+ while(gmpu_reg_info[i].name!=NULL) {
+ if(!strcmp(gmpu_reg_info[i].name, str)) {
+ return gmpu_reg_info[i].index;
+ }
+ i++;
+ }
+
+ return -1;
+}
+
+static int
+gmpu_assemble_opcode(unsigned int *opcode, gmpu_opc_info_t opcode_info, int insn_field_signed, const char *insn, const char *op1, const char *op2)
+{
+
+ // if insn ended in s, and GMPU_FIELD_SIGNED not set, abort
+ if(insn_field_signed && !(opcode_info.fields & GMPU_FIELD_SIGNED)) {
+ as_bad(_("Unknown opcode '%ss'"), insn);
+ return -1;
+ }
+
+ // check arity
+ switch(opcode_info.arity) {
+ case 0:
+ if(op1!=NULL || op2!=NULL) {
+ as_bad(_("Opcode '%s' takes no operands"), insn);
+ return -1;
+ }
+ break;
+ case 1:
+ if(op1==NULL || op2!=NULL) {
+ as_bad(_("Opcode '%s' takes exactly one operand"), insn);
+ return -1;
+ }
+ break;
+ case 2:
+ if(op1==NULL || op2==NULL) {
+ as_bad(_("Opcode '%s' takes exactly two operands"), insn);
+ return -1;
+ }
+ break;
+ default:
+ as_bad(_("Internal error: opcode table specifies invalid arity"));
+ return -1;
+ break;
+ }
+
+ *opcode = 0;
+
+ *opcode = opcode_info.bits & opcode_info.mask;
+
+ if(opcode_info.fields & GMPU_FIELD_SIGNED) {
+ if(insn_field_signed) {
+ *opcode |= ( 1 << GMPU_FIELD_SIGNED_BIT );
+ }
+ }
+
+ if(opcode_info.fields & GMPU_FIELD_DSTREG) {
+ //if(op1[0]=='[' && op1[strlen(op1)-1]==']') {
+ //}
+
+ int register_index = gmpu_parse_register(op1);
+
+ if(register_index<0) {
+ as_bad(_("Invalid register operand '%s'"), op1);
+ return -1;
+ } else {
+ *opcode |= (register_index << GMPU_FIELD_DSTREG_BIT);
+ }
+ }
+
+ if(opcode_info.fields & GMPU_FIELD_SRCREG) {
+ int register_index = gmpu_parse_register(op2);
+
+ if(register_index<0) {
+ as_bad(_("Invalid register operand '%s'"), op2);
+ return -1;
+ } else {
+ *opcode |= (register_index << GMPU_FIELD_SRCREG_BIT);
+ }
+ }
+
+ if(opcode_info.fields & GMPU_FIELD_MOVIMM) {
+ unsigned int imm = 0;
+
+ imm &= (2^GMPU_FIELD_MOVIMM_SIZE)-1;
+ *opcode |= (imm << GMPU_FIELD_MOVIMM_BIT);
+ }
+
+ return 0;
+}
+
void
md_assemble (char *str)
{
@@ -64,13 +161,94 @@ md_assemble (char *str)
size_t opcode_idx = 0;
int valid_opcode = 0;
-
str = strip_spaces(str);
+ int insn_field_signed = 0;
+ char *insn = str;
+ char *op1 = NULL;
+ char *op2 = NULL;
+
+ int cidx = 0;
+ int length = strlen(str);
+
+ // start parsing
+
+ // skip instruction
+ while(cidx<length && str[cidx]!=' ') cidx++;
+ // mark end of instruction
+ if(cidx<length) {
+ str[cidx]=0;
+ cidx++;
+ }
+
+ if(insn[strlen(insn)-1]=='s') {
+ insn_field_signed=1;
+ insn[strlen(insn)-1]=0;
+ }
+
+ // skip whitespace
+ while(cidx<length && str[cidx]==' ') cidx++;
+ if(cidx<length) {
+ op1 = str+cidx;
+ cidx++;
+ }
+
+ int seen_comma=0;
+ // skip op1
+ while(cidx<length && str[cidx]!=' ' && str[cidx]!=',') cidx++;
+ // mark end of op1
+ if(cidx<length) {
+ if(str[cidx]==',') seen_comma=1;
+ str[cidx]=0;
+ cidx++;
+ }
+
+ if(!seen_comma) {
+ // skip whitespace
+ while(cidx<length && str[cidx]==' ') cidx++;
+ if(cidx<length && str[cidx]==',') {
+ seen_comma=1;
+ }
+ }
+
+ // skip whitespace
+ while(cidx<length && str[cidx]==' ') cidx++;
+
+ if(cidx<length) {
+ if(seen_comma) {
+ op2 = str+cidx;
+ }
+ cidx++;
+ }
+
+ if(op2!=NULL) {
+ // skip op2
+ while(cidx<length && str[cidx]!=' ') cidx++;
+ // mark end of op2
+ if(cidx<length) {
+ str[cidx]=0;
+ cidx++;
+ }
+ }
+
+ // check remainder of line (only spaces, stop checking at ;)
+ while(cidx<length && str[cidx]==' ') cidx++;
+ if( (cidx<length) && str[cidx]!=';') {
+ as_bad (_("Trailing garbage '%s'"), str+cidx);
+ return;
+ }
+
+
+ // / done parsing
+
+ // match insn against opcode table
while(NULL != gmpu_opc_info[opcode_idx].name) {
- if(!strcmp(str, gmpu_opc_info[opcode_idx].name)) {
- opcode = gmpu_opc_info[opcode_idx].bits & gmpu_opc_info[opcode_idx].mask;
- valid_opcode=1;
+ if(!strcmp(insn, gmpu_opc_info[opcode_idx].name)) {
+ if(gmpu_assemble_opcode(&opcode, gmpu_opc_info[opcode_idx],insn_field_signed,insn,op1,op2)) {
+ as_bad(_("Unable to assemble opcode.."));
+ } else {
+ valid_opcode=1;
+ }
break;
}
opcode_idx++;
@@ -82,7 +260,7 @@ md_assemble (char *str)
*((unsigned int *)to)=htonl(opcode);
//memcpy(to, &opcode, 4);
} else {
- as_bad (_("Unknown instruction '%s'"), str);
+ as_bad (_("Unknown instruction '%s'"), insn);
}
}
diff --git a/include/opcode/gmpu.h b/include/opcode/gmpu.h
index dcbfbaa..a2f81db 100644
--- a/include/opcode/gmpu.h
+++ b/include/opcode/gmpu.h
@@ -29,9 +29,16 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
#define GMPU_FIELD_SRCREG_BIT 19
#define GMPU_FIELD_SRCREG_SIZE 4
+#define GMPU_FIELD_MOVIMM (1<<3)
+#define GMPU_FIELD_MOVIMM_BIT 0
+#define GMPU_FIELD_MOVIMM_SIZE 23
+
+#define GMPU_FIELD_DSTREG_INDIRECT (1<<4)
+
typedef struct gmpu_opc_info_t
{
const char *name;
+ int arity;
int dw;
unsigned int mask;
unsigned int bits;
diff --git a/opcodes/gmpu-opc.c b/opcodes/gmpu-opc.c
index 87859d9..948e217 100644
--- a/opcodes/gmpu-opc.c
+++ b/opcodes/gmpu-opc.c
@@ -26,12 +26,12 @@
const gmpu_opc_info_t gmpu_opc_info[] =
{
-{ "nop", 0, 0xffffffffU, 0x00000000U, 0},
-{ "halt", 0, 0xf0000000U, 0xf0000000U, 0},
-{ "mov", 0, 0xf0000000U, 0x10000000U, GMPU_FIELD_SIGNED},
-{ "add", 0, 0xf0000000U, 0x10000000U, GMPU_FIELD_SIGNED},
-{ "adds", 0, 0xf0000000U, 0x10000000U, GMPU_FIELD_SIGNED},
-{ NULL, 0, 0, 0, 0}
+{ "nop", 0, 0, 0xffffffffU, 0x00000000U, 0},
+{ "halt", 0, 0, 0xf0000000U, 0xf0000000U, 0},
+{ "mov", 2, 0, 0xf0000000U, 0x10000000U, GMPU_FIELD_SIGNED | GMPU_FIELD_DSTREG | GMPU_FIELD_DSTREG_INDIRECT | GMPU_FIELD_MOVIMM },
+{ "add", 2, 0, 0xf0000000U, 0x40000000U, GMPU_FIELD_SIGNED | GMPU_FIELD_DSTREG | GMPU_FIELD_SRCREG },
+{ "sub", 2, 0, 0xf0000000U, 0x50000000U, GMPU_FIELD_SIGNED | GMPU_FIELD_DSTREG | GMPU_FIELD_SRCREG },
+{ NULL, 0, 0, 0, 0, 0}
};
const gmpu_reg_info_t gmpu_reg_info[] =
@@ -47,5 +47,6 @@ const gmpu_reg_info_t gmpu_reg_info[] =
{ "ip", 1, 8 },
{ "sp", 1, 9 },
{ "sr", 1, 10 },
+{ NULL, 0, 0 }
};
--
1.9.1
From cd2d38c9fbca06c8c886fe8705684529d580393a Mon Sep 17 00:00:00 2001
From: Koen Martens <gmc@sonologic.nl>
Date: Wed, 24 Jun 2015 21:05:04 +0200
Subject: [PATCH 08/25] gmpu: implement mov immediate and store - disallow cpu
regs
---
gas/config/tc-gmpu.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++-----
include/opcode/gmpu.h | 2 ++
2 files changed, 66 insertions(+), 6 deletions(-)
diff --git a/gas/config/tc-gmpu.c b/gas/config/tc-gmpu.c
index 29dd774..0172229 100644
--- a/gas/config/tc-gmpu.c
+++ b/gas/config/tc-gmpu.c
@@ -48,6 +48,23 @@ md_begin (void)
}
+static int
+parse_constant (const char *s, expressionS *op)
+{
+ char *saved = input_line_pointer;
+
+ input_line_pointer=(char *)s;
+ expression(op);
+ input_line_pointer=saved;
+
+ if(op->X_op==O_constant) {
+ return 0;
+ }
+
+ return -1;
+}
+
+
static char *
strip_spaces(char *str)
{
@@ -63,7 +80,10 @@ gmpu_parse_register(const char *str)
while(gmpu_reg_info[i].name!=NULL) {
if(!strcmp(gmpu_reg_info[i].name, str)) {
- return gmpu_reg_info[i].index;
+ if(!gmpu_reg_info[i].cpu) {
+ return gmpu_reg_info[i].index;
+ }
+ break;
}
i++;
}
@@ -117,11 +137,43 @@ gmpu_assemble_opcode(unsigned int *opcode, gmpu_opc_info_t opcode_info, int insn
}
}
+ static char dst_op[GMPU_REGNAME_SIZE];
+
if(opcode_info.fields & GMPU_FIELD_DSTREG) {
- //if(op1[0]=='[' && op1[strlen(op1)-1]==']') {
- //}
+ int register_index = -1;
+
+ // note that only mov uses indirect dst, so we assume the insn
+ // is mov (and thus we need to set the 2 lsb of the opcode field
+ // to indicate load, store or reg-to-reg
+ if(op1[0]=='[' && op1[strlen(op1)-1]==']') {
+ memcpy(dst_op, op1+1, strlen(op1)-2);
+ dst_op[strlen(op1)-1] = 0;
+
+ register_index = gmpu_parse_register(dst_op);