summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenedikt Böhm <bb@xnull.de>2009-07-07 09:46:27 +0200
committerBenedikt Böhm <bb@xnull.de>2009-07-07 09:46:27 +0200
commitd15276557c65de2a1941632ec9024dea261cce26 (patch)
treea6a71e24e428f40bf2bdc54d2d4efaf4561786c9
parentb5d10e72de8d93a232886f069db9791b85c3e332 (diff)
downloadswppy-d15276557c65de2a1941632ec9024dea261cce26.tar.gz
swppy-d15276557c65de2a1941632ec9024dea261cce26.tar.xz
swppy-d15276557c65de2a1941632ec9024dea261cce26.zip
make instruction 64-bit wide to support more than 32 registers
-rw-r--r--src/emu/asm.c32
-rw-r--r--src/emu/asm.h4
-rw-r--r--src/emu/cpu.c53
-rw-r--r--src/emu/cpu.h4
-rw-r--r--src/emu/opc.c10
-rw-r--r--src/emu/opc.h19
-rw-r--r--src/emu/riscas.c6
-rw-r--r--src/emu/risci.c26
-rw-r--r--src/emu/syscall.c1
-rw-r--r--test/test5.t1
10 files changed, 82 insertions, 74 deletions
diff --git a/src/emu/asm.c b/src/emu/asm.c
index 4548b48..85f3293 100644
--- a/src/emu/asm.c
+++ b/src/emu/asm.c
@@ -1,54 +1,52 @@
#include <stdio.h>
#include <stdint.h>
+#include <inttypes.h>
#include "cpu.h"
#include "log.h"
#include "opc.h"
-#define REGa(x) (((x) & 0x1F) << 21)
-#define REGb(x) (((x) & 0x1F) << 16)
-#define REGc(x) (((x) & 0x1F) << 11)
-#define IMMc(x) ((x) & 0xFFFF)
+#define REGa(x) (((x) & 0x1FFF) << 45)
+#define REGb(x) (((x) & 0x1FFF) << 32)
+#define REGc(x) (((x) & 0x1FFF) << 19)
+#define IMMc(x) ((x) & 0xFFFFFFFF)
-uint32_t compile(const char *line)
+inst_t compile(const char *line)
{
char mnem[5];
- int32_t a = 0, b = 0, c = 0;
- static size_t regs = 0;
+ int64_t a = 0, b = 0, c = 0;
/* register file size */
- if (sscanf(line, ".REGS %d", &a) == 1) {
- regs = a;
+ if (sscanf(line, ".REGS %"SCNi64"", &a) == 1)
return a;
- }
/* ADD, SUB, MUL, DIV, MOD, AND, OR */
- if (sscanf(line, "%4s r%d, r%d, r%d", mnem, &a, &b, &c) == 4)
+ if (sscanf(line, "%4s r%"SCNi64", r%"SCNi64", r%"SCNi64"", mnem, &a, &b, &c) == 4)
return mnemonic2opc(mnem) | REGa(a) | REGb(b) | REGc(c);
/* LW, SW */
- if (sscanf(line, "%4s r%d, r%d, %d", mnem, &a, &b, &c) == 4)
+ if (sscanf(line, "%4s r%"SCNi64", r%"SCNi64", %"SCNi64"", mnem, &a, &b, &c) == 4)
return mnemonic2opc(mnem) | REGa(a) | REGb(b) | IMMc(c);
/* CMP */
- if (sscanf(line, "%4s r%d, r%d", mnem, &a, &b) == 3)
+ if (sscanf(line, "%4s r%"SCNi64", r%"SCNi64"", mnem, &a, &b) == 3)
return mnemonic2opc(mnem) | REGa(a) | REGb(b);
/* MOV, BEZ */
- if (sscanf(line, "%4s r%2d, %d", mnem, &a, &c) == 3)
+ if (sscanf(line, "%4s r%"SCNi64", %"SCNi64"", mnem, &a, &c) == 3)
return mnemonic2opc(mnem) | REGa(a) | IMMc(c);
/* EQ, NE, LT, LE, GE, GT, PUSH, POP */
- if (sscanf(line, "%4s r%d", mnem, &a) == 2)
+ if (sscanf(line, "%4s r%"SCNi64"", mnem, &a) == 2)
return mnemonic2opc(mnem) | REGa(a);
/* JMP, CALL */
- if (sscanf(line, "%4s %d", mnem, &c) == 2)
+ if (sscanf(line, "%4s %"SCNi64"", mnem, &c) == 2)
return mnemonic2opc(mnem) | IMMc(c);
/* RET, SYS */
if (sscanf(line, "%4s", mnem) == 1)
return mnemonic2opc(mnem);
- return 0xFFFFFFFF;
+ return 0xFFFFFFFFFFFFFFFF;
}
diff --git a/src/emu/asm.h b/src/emu/asm.h
index 9a4fd37..102ae65 100644
--- a/src/emu/asm.h
+++ b/src/emu/asm.h
@@ -3,6 +3,8 @@
#include <stdint.h>
-uint32_t compile(const char *line);
+#include "opc.h"
+
+inst_t compile(const char *line);
#endif
diff --git a/src/emu/cpu.c b/src/emu/cpu.c
index f083283..522e2f2 100644
--- a/src/emu/cpu.c
+++ b/src/emu/cpu.c
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include <signal.h>
#include <string.h>
+#include <inttypes.h>
#include "cpu.h"
#include "log.h"
@@ -11,7 +12,7 @@
#include "opc.h"
#include "syscall.h"
-/* stack pointer register*/
+/* stack pointer register */
uint32_t SP;
/* base pointer register */
@@ -31,19 +32,19 @@ uint32_t *GPR;
/* extract operands from the instruction register */
static inline
-uint32_t __OPEXT(uint32_t IR, uint8_t start, uint8_t length)
+uint64_t __OPEXT(inst_t IR, uint8_t start, uint8_t length)
{
- return (IR >> start) & ((1 << length) - 1);
+ return (IR >> start) & ((1ULL << length) - 1);
}
#define OPEXT(start, length) __OPEXT(IR, start, length)
/* operands */
-#define OPCODE OPEXT(26, 6)
-#define REGa OPEXT(21, 5)
-#define REGb OPEXT(16, 5)
-#define REGc OPEXT(11, 5)
-#define IMMc OPEXT(0, 16)
+#define OPCODE OPEXT(58, 6)
+#define REGa OPEXT(45, 13)
+#define REGb OPEXT(32, 13)
+#define REGc OPEXT(19, 13)
+#define IMMc OPEXT(0, 32)
/* cpu traps */
void trap(int num)
@@ -67,11 +68,11 @@ void trap(int num)
}
}
-void execute(uint32_t IR)
+void execute(inst_t IR)
{
/* decode op-code */
uint8_t opcode = OPCODE;
- int32_t a, b, c;
+ int64_t a, b, c;
if (opcode < OPC_MOV) {
/* arithmetic, logic, comparison */
@@ -79,7 +80,7 @@ void execute(uint32_t IR)
b = REGb;
c = REGc;
- debug("IP@%#08x: %-4s r%i, r%i, r%i", IP,
+ debug("IP@%#08x: %-4s r%"PRIi64", r%"PRIi64", r%"PRIi64, IP,
opc2mnemonic(IR), a, b, c);
}
@@ -90,17 +91,17 @@ void execute(uint32_t IR)
c = IMMc;
/* sign extension */
- if (c >= 0x8000)
- c -= 0x10000;
+ if (c >= 0x80000000)
+ c -= 0x100000000;
if (opcode < OPC_LW) {
- debug("IP@%#08x: %-4s r%i, %i", IP,
+ debug("IP@%#08x: %-4s r%"PRIi64", %"PRIi64, IP,
opc2mnemonic(IR), a, c);
} else if (opcode < OPC_PUSH) {
- debug("IP@%#08x: %-4s r%i, r%i, %i", IP,
+ debug("IP@%#08x: %-4s r%"PRIi64", r%"PRIi64", %"PRIi64, IP,
opc2mnemonic(IR), a, b, c);
} else {
- debug("IP@%#08x: %-4s r%i", IP,
+ debug("IP@%#08x: %-4s r%"PRIi64, IP,
opc2mnemonic(IR), a);
}
}
@@ -112,20 +113,20 @@ void execute(uint32_t IR)
c = IMMc;
/* sign extension */
- if (c >= 0x8000)
- c -= 0x10000;
+ if (c >= 0x80000000)
+ c -= 0x100000000;
switch (opcode) {
case OPC_BEZ:
- debug("IP@%#08x: %-4s r%i, %i", IP,
+ debug("IP@%#08x: %-4s r%"PRIi64", %"PRIi64, IP,
opc2mnemonic(IR), a, c);
break;
case OPC_JMP:
- debug("IP@%#08x: %-4s %i", IP,
+ debug("IP@%#08x: %-4s %"PRIi64, IP,
opc2mnemonic(IR), c);
break;
case OPC_CALL:
- debug("IP@%#08x: %-4s %i", IP,
+ debug("IP@%#08x: %-4s %"PRIi64, IP,
opc2mnemonic(IR), c);
break;
case OPC_RET:
@@ -215,16 +216,16 @@ void execute(uint32_t IR)
break;
case OPC_BEZ:
if (GPR[a] == 0) {
- IP += c * 4;
+ IP += c * sizeof(inst_t);
return;
}
break;
case OPC_JMP:
- IP += c * 4;
+ IP += c * sizeof(inst_t);
return;
case OPC_CALL:
- push(IP + 4);
- IP += c * 4;
+ push(IP + sizeof(inst_t));
+ IP += c * sizeof(inst_t);
return;
case OPC_RET:
IP = pop();
@@ -237,5 +238,5 @@ void execute(uint32_t IR)
trap(TRP_ILL);
}
- IP += 4;
+ IP += sizeof(inst_t);
}
diff --git a/src/emu/cpu.h b/src/emu/cpu.h
index 4867a8a..9294d7d 100644
--- a/src/emu/cpu.h
+++ b/src/emu/cpu.h
@@ -4,6 +4,8 @@
#include <stdint.h>
#include <stdbool.h>
+#include "opc.h"
+
/* cpu traps */
enum {
TRP_UNALIGNED,
@@ -33,6 +35,6 @@ extern bool N, Z;
extern uint32_t *GPR;
/* main cpu execution function */
-void execute(uint32_t IR);
+void execute(inst_t IR);
#endif
diff --git a/src/emu/opc.c b/src/emu/opc.c
index 3d62479..c9e5f8c 100644
--- a/src/emu/opc.c
+++ b/src/emu/opc.c
@@ -5,7 +5,7 @@
typedef struct opc_mapping {
const char *name;
- uint32_t opcode;
+ inst_t opcode;
} opc_mapping_t;
opc_mapping_t opc_map[] = {
@@ -36,19 +36,19 @@ opc_mapping_t opc_map[] = {
{ NULL, 0 }
};
-uint32_t mnemonic2opc(const char *mnemonic)
+inst_t mnemonic2opc(const char *mnemonic)
{
for (uint8_t i = 0; opc_map[i].name; i++) {
if (strcmp(opc_map[i].name, mnemonic) == 0)
- return opc_map[i].opcode << 26;
+ return opc_map[i].opcode << 58;
}
return ~0;
}
-const char *opc2mnemonic(uint32_t IR)
+const char *opc2mnemonic(inst_t IR)
{
- uint32_t opcode = IR >> 26;
+ inst_t opcode = IR >> 58;
for (uint8_t i = 0; opc_map[i].name; i++) {
if (opc_map[i].opcode == opcode)
diff --git a/src/emu/opc.h b/src/emu/opc.h
index 179f7b2..8720958 100644
--- a/src/emu/opc.h
+++ b/src/emu/opc.h
@@ -7,17 +7,17 @@
* ---------------------
*
* arithmetic:
- * |000|xxx|aaaaa|bbbbb|ccccc|00000000000|
+ * |000|xxx|aaaaaaaaaaaaa|bbbbbbbbbbbbb|ccccccccccccc|0000000000000000000|
* logic:
- * |001|xxx|aaaaa|bbbbb|ccccc|00000000000|
+ * |001|xxx|aaaaaaaaaaaaa|bbbbbbbbbbbbb|ccccccccccccc|0000000000000000000|
* comparison:
- * |010|xxx|aaaaa|bbbbb|0000000000000000|
+ * |010|xxx|aaaaaaaaaaaaa|bbbbbbbbbbbbb|00000000000000000000000000000000|
* load & store:
- * |011|xxx|aaaaa|bbbbb|cccccccccccccccc|
+ * |011|xxx|aaaaaaaaaaaaa|bbbbbbbbbbbbb|cccccccccccccccccccccccccccccccc|
* jump:
- * |100|xxx|aaaaa|00000|cccccccccccccccc|
+ * |100|xxx|aaaaaaaaaaaaa|0000000000000|cccccccccccccccccccccccccccccccc|
* misc:
- * |111|xxx|??????????????????????????|
+ * |111|xxx|??????????????????????????????????????????????????????????|
*
*/
@@ -57,8 +57,11 @@
/* misc */
#define OPC_SYS 070
+/* one instruction is 64 bit */
+typedef uint64_t inst_t;
+
/* conversion functions */
-uint32_t mnemonic2opc(const char *mnemonic);
-const char *opc2mnemonic(uint32_t IR);
+inst_t mnemonic2opc(const char *mnemonic);
+const char *opc2mnemonic(inst_t IR);
#endif
diff --git a/src/emu/riscas.c b/src/emu/riscas.c
index 7a4af47..5b6cac9 100644
--- a/src/emu/riscas.c
+++ b/src/emu/riscas.c
@@ -28,12 +28,12 @@ int main(int argc, char *argv[])
char line[128];
while (fgets(line, 128, sfd)) {
- uint32_t IR = compile(line);
+ inst_t IR = compile(line);
- if (IR == 0xFFFFFFFF)
+ if (IR == 0xFFFFFFFFFFFFFFFF)
die("illegal instruction: %s", line);
- fwrite(&IR, 4, 1, pfd);
+ fwrite(&IR, sizeof(inst_t), 1, pfd);
}
return 0;
diff --git a/src/emu/risci.c b/src/emu/risci.c
index 704ece8..1711089 100644
--- a/src/emu/risci.c
+++ b/src/emu/risci.c
@@ -17,8 +17,8 @@
#include "opc.h"
bool is_debug = false;
-size_t mem_size = 64 * 1024 * 1024;
-size_t reg_size = 0;
+uint64_t mem_size = 64 * 1024 * 1024;
+uint64_t reg_size = 0;
static
void usage(int rc)
@@ -42,17 +42,17 @@ void read_program(const char *program)
if (lstat(program, &sb) == -1)
pdie("cannot stat program");
- if (sb.st_size % 4)
- die("program does not align to op-code size of 4 bytes");
+ if (sb.st_size % sizeof(inst_t))
+ die("program does not align to instruction size of %zu bytes", sizeof(inst_t));
int pfd;
if ((pfd = open(program, O_RDONLY)) == -1)
pdie("could not open program");
/* initialize register file */
- assert(read(pfd, &reg_size, 4) == 4);
+ assert(read(pfd, &reg_size, sizeof(inst_t)) == sizeof(inst_t));
reg_size += 4;
- GPR = calloc(reg_size, 4);
+ GPR = calloc(reg_size, sizeof(uint32_t));
/* initialize pseudo registers */
BP = reg_size - 3;
@@ -61,15 +61,15 @@ void read_program(const char *program)
GPR[BP] = GPR[SP] = mem_size;
GPR[RV] = 0;
- assert(read(pfd, MEM, sb.st_size - 4) == sb.st_size - 4);
- memset(MEM + sb.st_size + 4, 0xFF, 4);
+ assert(read(pfd, MEM, sb.st_size - sizeof(inst_t)) == (ssize_t)(sb.st_size - sizeof(inst_t)));
+ memset(MEM + sb.st_size, 0xFF, sizeof(inst_t));
}
static
-uint32_t next_instruction(void)
+inst_t next_instruction(void)
{
- uint32_t tmp;
- memcpy(&tmp, &MEM[IP], 4);
+ inst_t tmp;
+ memcpy(&tmp, &MEM[IP], sizeof(inst_t));
return tmp;
}
@@ -85,7 +85,7 @@ int main(int argc, char *argv[])
case 'h':
usage(EXIT_SUCCESS);
case 'm':
- mem_size = atoi(optarg) * 4;
+ mem_size = atoi(optarg) * sizeof(uint32_t);
break;
case '?':
default:
@@ -97,7 +97,7 @@ int main(int argc, char *argv[])
argv += optind;
/* reserve memory */
- MEM = calloc(mem_size, sizeof(char));
+ MEM = calloc(mem_size, sizeof(uint8_t));
/* load program from file */
if (argc < 1)
diff --git a/src/emu/syscall.c b/src/emu/syscall.c
index aba3448..92cab22 100644
--- a/src/emu/syscall.c
+++ b/src/emu/syscall.c
@@ -1,5 +1,6 @@
#include <unistd.h>
#include <stdlib.h>
+#include <stdio.h>
#include <inttypes.h>
#include "cpu.h"
diff --git a/test/test5.t b/test/test5.t
index cfc094c..c6e786d 100644
--- a/test/test5.t
+++ b/test/test5.t
@@ -3,6 +3,7 @@ fun main[]
print x
y = call ggt2[30,40]
print y
+ @x == y
end
fun ggt1[x,y]