commit efd8c1bf29cc3a30053a4a4c7776fba70f29c2e3
parent 35a56d75b4612c7ee70e5819c6cdf87a98facd14
Author: Brian Swetland <swetland@frotz.net>
Date: Sun, 29 Jun 2025 17:19:10 -0700
sr32asm: add pseudo instructions and clean up
- add not, neg, and the various branch and set alias instructions
- rearrange the ins_...() inlines so their arguments match the
argument order in the assembly instructions rather than being
(mostly) backwards, aligned with the instruction encoding.
- code generation feels much more readable now
Diffstat:
2 files changed, 112 insertions(+), 31 deletions(-)
diff --git a/softrisc32/src/assemble-sr32.c b/softrisc32/src/assemble-sr32.c
@@ -240,6 +240,9 @@ enum tokens {
tSTW, tSTH, tSTB, tSTX,
tJAL, tSYSCALL, tBREAK, tSYSRET,
tNOP, tMV, tLI, tLA, tJ, tJR, tRET,
+ tNOT, tNEG, tSEQZ, tSNEZ, tSLTZ, tSGTZ,
+ tBEQZ, tBNEZ, tBLEZ, tBGEZ, tBLTZ, tBGTZ,
+ tBGT, tBLE, tBGTU, tBLEU,
tEQU, tBYTE, tHALF, tWORD,
NUMTOKENS,
};
@@ -255,7 +258,11 @@ char *tnames[] = { "<EOF>", "<EOL>", "IDENT", "REGISTER", "NUMBER", "STRING",
"LDW", "LDH", "LDB", "LDX", "LUI", "LDHU", "LDBU", "AUIPC",
"STW", "STH", "STB", "STX",
"JAL", "SYSCALL", "BREAK", "SYSRET",
+ // pseudo instructions
"NOP", "MV", "LI", "LA", "J", "JR", "RET",
+ "NOT", "NEG", "SEQZ", "SNEZ", "SLTZ", "SGTZ",
+ "BEQZ", "BNEZ", "BLEZ", "BGEZ", "BLTZ", "BGTZ",
+ "BGT", "BLE", "BGTU", "BLEU",
"EQU", "BYTE", "HALF", "WORD",
};
@@ -516,15 +523,15 @@ int parse_line(State *s) {
o = tok - tADD;
parse_2r_c(s, &t, &a);
parse_reg(s, &b);
- emit(ins_r(0, b, a, t, o));
+ emit(ins_r(o, t, a, b, 0));
break;
case tADDI: case tSUBI: case tANDI: case tORI:
case tXORI: case tSLLI: case tSRLI: case tSRAI:
case tSLTI: case tSLTUI:
o = tok - tADDI;
parse_2r_c(s, &t, &a);
- parse_num(s, &b);
- emit(ins_i(b, a, t, o));
+ parse_num(s, &i);
+ emit(ins_i(o, t, a, i));
break;
// todo: mul div
case tBEQ: case tBNE: case tBLT:
@@ -532,66 +539,140 @@ int parse_line(State *s) {
o = tok - tBEQ;
parse_2r_c(s, &a, &b);
parse_rel(s, TYPE_PCREL_S16, &i);
- emit(ins_b(i, a, b, o));
+ emit(ins_b(o, a, b, i));
break;
case tLDW: case tLDH: case tLDB: case tLDX:
case tLDHU: case tLDBU:
o = tok - tLDW;
parse_r_c(s, &t);
parse_memref(s, &a, &i);
- emit(ins_l(i, a, t, o));
+ emit(ins_l(o, t, a, i));
break;
case tLUI:
case tAUIPC:
o = tok - tLDW;
parse_r_c(s, &t);
parse_num(s, &i);
- emit(ins_l(i >> 16, 0, t, o));
+ emit(ins_l(o, t, 0, i >> 16));
break;
case tSTW: case tSTH: case tSTB: case tSTX:
o = tok - tSTW;
parse_r_c(s, &b);
parse_memref(s, &a, &i);
- emit(ins_s(i, a, b, o));
+ emit(ins_s(o, b, a, i));
break;
case tJAL:
parse_r_c(s, &t);
parse_rel(s, TYPE_PCREL_S21, &i);
- emit(ins_j(i, t, J_JAL));
+ emit(ins_j(J_JAL, t, i));
break;
case tSYSCALL:
parse_num(s, &i);
- emit(ins_j(i, 0, J_SYSCALL));
+ emit(ins_j(J_SYSCALL, 0, i));
break;
case tBREAK:
- emit(ins_j(0, 0, J_BREAK));
+ emit(ins_j(J_BREAK, 0, 0));
break;
case tSYSRET:
- emit(ins_j(0, 0, J_SYSRET));
+ emit(ins_j(J_SYSRET, 0, 0));
break;
case tJALR:
parse_2r_c(s, &t, &a);
if (s->tok == tNUMBER) {
- emit(ins_i(s->num, a, t, IR_JALR));
+ emit(ins_i(IR_JALR, t, a, s->num));
} else if (s->tok == tREGISTER) {
- emit(ins_r(0, s->num, a, t, IR_JALR));
+ emit(ins_r(IR_JALR, t, a, s->num, 0));
} else {
die("expected register or immediate");
}
break;
+ case tNOT:
+ parse_2r(s, &t, &a);
+ emit(ins_i(IR_XOR, t, a, -1));
+ break;
+ case tNEG:
+ parse_2r(s, &t, &a);
+ emit(ins_r(IR_SUB, t, 0, a, 0));
+ break;
+ case tSEQZ:
+ parse_2r(s, &t, &a);
+ emit(ins_i(IR_SLTU, t, a, 1));
+ break;
+ case tSNEZ:
+ parse_2r(s, &t, &a);
+ emit(ins_r(IR_SLTU, t, 0, a, 0));
+ break;
+ case tSLTZ:
+ parse_2r(s, &t, &a);
+ emit(ins_r(IR_SLT, t, a, 0, 0));
+ break;
+ case tSGTZ:
+ parse_2r(s, &t, &a);
+ emit(ins_r(IR_SLT, t, 0, a, 0));
+ break;
+ case tBEQZ:
+ parse_r_c(s, &a);
+ parse_rel(s, TYPE_PCREL_S16, &i);
+ emit(ins_b(B_BEQ, a, 0, i));
+ break;
+ case tBNEZ:
+ parse_r_c(s, &a);
+ parse_rel(s, TYPE_PCREL_S16, &i);
+ emit(ins_b(B_BNE, a, 0, i));
+ break;
+ case tBLEZ:
+ parse_r_c(s, &a);
+ parse_rel(s, TYPE_PCREL_S16, &i);
+ emit(ins_b(B_BGE, 0, a, i));
+ break;
+ case tBGEZ:
+ parse_r_c(s, &a);
+ parse_rel(s, TYPE_PCREL_S16, &i);
+ emit(ins_b(B_BGE, 0, a, i));
+ break;
+ case tBLTZ:
+ parse_r_c(s, &a);
+ parse_rel(s, TYPE_PCREL_S16, &i);
+ emit(ins_b(B_BLT, a, 0, i));
+ break;
+ case tBGTZ:
+ parse_r_c(s, &a);
+ parse_rel(s, TYPE_PCREL_S16, &i);
+ emit(ins_b(B_BLT, 0, a, i));
+ break;
+ case tBGT:
+ parse_2r_c(s, &a, &b);
+ parse_rel(s, TYPE_PCREL_S16, &i);
+ emit(ins_b(B_BLT, b, a, i));
+ break;
+ case tBLE:
+ parse_2r_c(s, &a, &b);
+ parse_rel(s, TYPE_PCREL_S16, &i);
+ emit(ins_b(B_BGE, b, a, i));
+ break;
+ case tBGTU:
+ parse_2r_c(s, &a, &b);
+ parse_rel(s, TYPE_PCREL_S16, &i);
+ emit(ins_b(B_BLTU, b, a, i));
+ break;
+ case tBLEU:
+ parse_2r_c(s, &a, &b);
+ parse_rel(s, TYPE_PCREL_S16, &i);
+ emit(ins_b(B_BGEU, b, a, i));
+ break;
case tJR:
parse_reg(s, &a);
- emit(ins_r(0, 0, a, 0, IR_JALR));
+ emit(ins_r(IR_JALR, 0, a, 0, 0));
break;
case tRET:
- emit(ins_r(0, 0, 1, 0, IR_JALR));
+ emit(ins_r(IR_JALR, 0, 1, 0, 0));
break;
case tNOP:
- emit(ins_i(0, 0, 0, IR_ADD));
+ emit(ins_i(IR_ADD, 0, 0, 0));
break;
case tMV:
parse_2r(s, &t, &a);
- emit(ins_r(0, 0, a, t, IR_ADD));
+ emit(ins_r(IR_ADD, t, a, 0, 0));
break;
case tLI:
parse_r_c(s, &t);
@@ -600,25 +681,25 @@ int parse_line(State *s) {
} else {
parse_num(s, &i);
if (is_signed16(i)) {
- emit(ins_i(i, 0, t, IR_ADD));
+ emit(ins_i(IR_ADD, t, 0, i));
} else {
uint32_t hi = i >> 16;
uint32_t lo = i & 0xffff;
if (lo & 0x8000) hi += 1;
- emit(ins_l(hi, 0, t, L_LUI));
- emit(ins_i(lo, t, t, IR_ADD));
+ emit(ins_l(L_LUI, t, 0, hi));
+ emit(ins_i(IR_ADD, t, t, lo));
}
}
break;
case tLA:
parse_r_c(s, &t);
parse_rel(s, TYPE_PCREL_HILO, &i);
- emit(ins_l(i >> 16, 0, t, L_AUIPC));
- emit(ins_i(i & 0xFFFF, t, t, IR_ADD));
+ emit(ins_l(L_AUIPC, t, 0, i >> 16));
+ emit(ins_i(IR_ADD, t, t, i & 0xFFFF));
break;
case tJ:
parse_rel(s, TYPE_PCREL_S21, &i);
- emit(ins_j(i, 0, J_JAL));
+ emit(ins_j(J_JAL, 0, i));
break;
case tEQU:
require(s, tIDENT);
diff --git a/softrisc32/src/sr32.h b/softrisc32/src/sr32.h
@@ -22,8 +22,8 @@
#define B_BNE 1
#define B_BLT 2
#define B_BLTU 3
-#define B_GE 4
-#define B_GEU 5
+#define B_BGE 4
+#define B_BGEU 5
#define L_LDW 0
#define L_LDH 1
@@ -44,22 +44,22 @@
#define J_BREAK 2
#define J_SYSRET 3
-static inline uint32_t ins_i(uint32_t i, uint32_t a, uint32_t t, uint32_t o) {
+static inline uint32_t ins_i(uint32_t o, uint32_t t, uint32_t a, uint32_t i) {
return (i << 16) | ((a & 0x1F) << 11) | ((t & 0x1F) << 6) | (o & 0xF);
}
-static inline uint32_t ins_r(uint32_t n, uint32_t b, uint32_t a, uint32_t t, uint32_t o) {
+static inline uint32_t ins_r(uint32_t o, uint32_t t, uint32_t a, uint32_t b, uint32_t n) {
return ((n & 7) << 21) | ((b & 0x1F) << 16) | ((a & 0x1F) << 11) | ((t & 0x1F) << 6) | (o & 0xF) | 0x10;
}
-static inline uint32_t ins_l(uint32_t i, uint32_t a, uint32_t t, uint32_t o) {
+static inline uint32_t ins_l(uint32_t o, uint32_t t, uint32_t a, uint32_t i) {
return (i << 16) | ((a & 0x1F) << 11) | ((t & 0x1F) << 6) | (o & 7) | 0x20;
}
-static inline uint32_t ins_s(uint32_t i, uint32_t a, uint32_t b, uint32_t o) {
+static inline uint32_t ins_s(uint32_t o, uint32_t b, uint32_t a, uint32_t i) {
return (i << 16) | ((a & 0x1F) << 11) | ((b & 0x1F) << 6) | (o & 7) | 0x28;
}
-static inline uint32_t ins_b(uint32_t i, uint32_t a, uint32_t b, uint32_t o) {
+static inline uint32_t ins_b(uint32_t o, uint32_t a, uint32_t b, uint32_t i) {
return (i << 16) | ((a & 0x1F) << 11) | ((b & 0x1F) << 6) | (o & 7) | 0x30;
}
-static inline uint32_t ins_j(uint32_t i, uint32_t t, uint32_t o) {
+static inline uint32_t ins_j(uint32_t o, uint32_t t, uint32_t i) {
return (i << 11) | ((t & 0x1F) << 6) | (o & 7) | 0x38;
}