@@ 7,7 7,8 @@
#define MAXTOKEN 32
#define MAXSYMBOL 128
#define MAXARGS 3
-#define MEMORY 32
+// FIXME make program growth dynamic
+#define MEMORY 128
typedef struct Inst Inst;
struct Inst {
@@ 125,6 126,16 @@ matchopcode(char* t)
return -1;
}
+int
+matchtrapcode(char* t)
+{
+ for(int i = TRAP_GETC; i < TRAP_COUNT; i++){
+ if(!strcmp(t, trap[i]))
+ return i;
+ }
+ return -1;
+}
+
void
parseargs(char* t, Inst* in)
{
@@ 142,14 153,11 @@ parseargs(char* t, Inst* in)
// FIXME should probably find some way to indicate larger arity errors here?
}
-u16int
-hexnparse(int b, char *s)
+u16int
+hexnparselit(int b, char *s)
{
u16int n;
long m;
- if(s[0] != 'x')
- syntaxerr(smprint("Not a hex value, must indicate base with a leading `x`: %s", s));
- s++;
m = strtol(s, 0, 16);
n = (u16int) m;
if(n != m || n >= (1 << b))
@@ 157,12 165,24 @@ hexnparse(int b, char *s)
return n;
}
+
+u16int
+hexnparse(int b, char *s)
+{
+ if(s[0] != 'x')
+ syntaxerr(smprint("Not a hex value, must indicate base with a leading `x`: %s", s));
+ s++;
+ return hexnparselit(b, s);
+}
+
+
void
validate(Inst *in)
{
int arity;
int p;
// Validate arity
+
switch(in->op){
case OP_ADD:
case OP_AND:
@@ 182,6 202,7 @@ validate(Inst *in)
case OP_JMP:
case OP_JSR:
case OP_TRAP:
+ case OP_DATA:
arity = 1;
break;
case OP_RTI:
@@ 257,6 278,9 @@ validate(Inst *in)
case OP_TRAP:
in->p_arg[0] = hexnparse(8, in->arg[0]);
break;
+ case OP_DATA:
+ in->p_arg[0] = hexnparse(16, in->arg[0]);
+ break;
default:
Reg:
// They're all registers
@@ 298,6 322,10 @@ parseline(char *l)
if(c == 0) return 0;
l += c;
if(strcmp(t,".END") == 0) {
+ inst = newinst(OP_TRAP);
+ inst->p_arg[0] = TRAP_HALT;
+ inst->argc++;
+ pc++;
return -1; // We're done parsing!
} else if(strcmp(t,".ORIG") == 0){
//FIXME: only supporting hex for now
@@ 315,12 343,43 @@ parseline(char *l)
if(debug)
print("updated origin to %x\n", orig);
return 0;
+ } else if(strcmp(t,".FILL") == 0) {
+ l++;
+ inst = newinst(OP_DATA);
+ gettoken(&t, l);
+ parseargs(t, inst);
+ goto validate;
+ } else if(strcmp(t,".BLKW") == 0) {
+ l++;
+ gettoken(&t, l);
+ for(int i = 0; i<hexnparse(16, t); i++){
+ inst = newinst(OP_DATA);
+ inst->arg[0] = "x0";
+ inst->argc = 1;
+ validate(inst);
+ pc++;
+ }
+ return 1;
+ } else if(strcmp(t,".STRINGZ") == 0) {
+ // FIXME very hex
+ l+=2;
+ gettoken(&t, l);
+ for(int i = 0; i<=strlen(t); i+=2){
+ u16int p = 0;
+ p |= t[i];
+ if(t[i] != 0)
+ p|= t[i+1] << 8;
+ inst = newinst(OP_DATA);
+ inst->p_arg[0] = hexnparselit(16, (char *) &p);
+ inst->argc++;
+ pc++;
+ }
+ return 1;
} else if(strcmp(t,"NOP") == 0) {
inst = newinst(OP_BR);
inst->arg[0] = "x0";
inst->argc++;
goto validate;
- return 1;
} else if(strcmp(t,"RET") == 0) {
inst = newinst(OP_JMP);
inst->arg[0] = "R7";
@@ 347,9 406,17 @@ parseline(char *l)
pos++;
} else {
int op = matchopcode(t);
+ if(op == -1){
+ op = matchtrapcode(t);
+ if(op == -1)
+ syntaxerr(smprint("Invalid instruction `%s`", t));
+ inst = newinst(OP_TRAP);
+ inst->argc++;
+ inst->p_arg[0] = op;
+ pc++;
+ return 1;
+ }
pos++;
- if(op == -1)
- syntaxerr(smprint("Invalid instruction `%s`", t));
l++;
inst = newinst(op);
}
@@ 369,7 436,7 @@ parseline(char *l)
return 1;
}
}
- fprint(2, "Should not get here\n");
+ syntaxerr("Should not get here\n");
return -1;
}
@@ 402,12 469,12 @@ maplabels(void)
packed_offset = offset * -1;
packed_offset = ~packed_offset;
packed_offset++;
+ } else {
+ packed_offset = offset;
}
mem[p]->p_arg[last] = packed_offset & mask;
- /* FIXME: test this
- if(offset != signextend(mem[p]->p_arg[last], bits))
+ if(packed_offset != signextend(mem[p]->p_arg[last], bits))
syntaxerr(smprint("Memory offset %x for label %s is too big to fit the argument for opcode %s", offset, symtab[j].label, opcode[mem[p]->op]));
- */
found++;
break;
}
@@ 423,6 490,9 @@ writeinst(Inst *i, FILE *f)
u16int code = 0;
code |= i->op << 12;
switch(i->op){
+ case OP_DATA:
+ code = i->p_arg[0];
+ break;
case OP_ADD:
case OP_AND:
code |= i->p_arg[0] << 9;
@@ 515,7 585,10 @@ main(int argc, char* argv[])
}
u16int o = swap16(orig);
fwrite(&o, 2, 1, out);
- for(int i = 0; i < memc; i++)
+ for(int i = 0; i < memc; i++){
writeinst(mem[i], out);
+ }
+ //fflush(out);
+ //fclose(out);
exits(nil);
}
@@ 1,5 1,6 @@
#define OFFSET 0x3000
#define MEMORY_MAX (1 << 16)
+#define OP_DATA 65535
enum
{
@@ 68,7 69,8 @@ static const char* const opcode[] =
[OP_JMP] = "JMP", // jump
[OP_RES] = "RES", // reserved (unused)
[OP_LEA] = "LEA", // load effective address
- [OP_TRAP] = "TRAP" // execute trap
+ [OP_TRAP] = "TRAP", // execute trap
+ [OP_DATA] = "DATA" // Dummy op for raw data
};
enum
@@ 92,7 94,8 @@ enum
TRAP_PUTS,
TRAP_IN,
TRAP_PUTSP,
- TRAP_HALT
+ TRAP_HALT,
+ TRAP_COUNT
};
static const char* const trap[] =
@@ 1,4 1,5 @@
.ORIG x3000
+ NOP
ADD R2,R2,x6 ; we need 6 loops to get to 'h'
NOT R2,R2 ; we want to be able to subtract this number so we'll 2's complements it
ADD R2,R2,x1
@@ 8,4 9,19 @@ LOOPH ADD R0,R0,xf
BRn LOOPH
ADD R0,R0,xe
TRAP x21
+E .FILL x65
+L .FILL x6c
+O .FILL x6f
+ LD R0,E
+ TRAP x21
+ LD R0,L
+ TRAP x21
+ TRAP x21
+ LD R0,O
+ TRAP x21
+ .BLKW x5
+ LEA R0,WRLD
+ PUTSP
+ HALT
+WRLD .STRINGZ x20776f726c64210a
.END