Skip to content

Commit

Permalink
Improve immediate value handling
Browse files Browse the repository at this point in the history
-Differentiate between the various short/quick
 immediate value types: signed, 1-32 unsigned,
 0-31 unsigned, shift left 1-32 unsigned (WTF!?!),
 and relative jump offset signed. Most of this is
 handled at stringification time to keep the core
 deserialization code simple, but sign extension
 is handled by the deserialization code.

-Print relative jump offsets in a format that MAC
 and RMAC can assemble.

-Add a very incomplete test suite. Run "make" in
 the "test" subdirectory to run it.
  • Loading branch information
cubanismo committed Jun 14, 2022
1 parent 6940bd4 commit 553a65a
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 33 deletions.
15 changes: 11 additions & 4 deletions jrisc_inst.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ jriscValidateCondition(uint8_t raw, uint8_t *conditionOut)
static enum JRISC_Error
jriscValidateImmediate(uint8_t raw, uint8_t *immediateOut)
{
/* XXX Handle signed/unsigned immediates separately */
if (raw & ~JRISC_REG_MASK) {
return JRISC_ERROR_invalidValue;
}
Expand Down Expand Up @@ -128,10 +127,18 @@ jriscRegFromRaw(uint8_t raw,
if (ret != JRISC_success) return ret;
break;

case JRISC_pcoffset: /* Fall through */
case JRISC_immediate:
ret = jriscValidateImmediate(raw, &out.val.immediate);
case JRISC_pcoffset: /* Fall through */
case JRISC_simmediate: /* Fall through */
case JRISC_shlimmediate: /* Fall through */
case JRISC_uimmediate: /* Fall through */
case JRISC_zuimmediate: /* Fall through*/
ret = jriscValidateImmediate(raw, &out.val.uimmediate);
if (ret != JRISC_success) return ret;

if (((type == JRISC_pcoffset) || (type == JRISC_simmediate)) &&
(out.val.uimmediate & 0x10)) {
out.val.simmediate = out.val.simmediate | 0xe0;
}
break;

case JRISC_flag:
Expand Down
4 changes: 2 additions & 2 deletions jrisc_inst.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ struct JRISC_OpReg {
union {
enum JRISC_Reg reg;
uint8_t condition;
/* XXX Handle signed/unsigned immediates separately */
uint8_t immediate;
uint8_t uimmediate;
int8_t simmediate;
bool flag;
} val;
};
Expand Down
37 changes: 31 additions & 6 deletions jrisc_inst_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <assert.h>

static const char *jriscOpNameToStringTable[] = {
#define JRISC_OP(opName, opNum, regSrcType, regDstType, swapRegs, cpus) #opName,
Expand Down Expand Up @@ -61,6 +62,12 @@ static const char *jriscOpNameToString(enum JRISC_OpName opName)
outLength += tmpLength; \
} while (0)

static inline uint8_t
jriscRegUnsignedValue(const struct JRISC_OpReg *reg)
{
return reg->val.uimmediate ? reg->val.uimmediate : 32;
}

/* Returns true if the register field is something visible */
static bool
jriscRegToString(const struct JRISC_OpReg *reg,
Expand All @@ -82,10 +89,12 @@ jriscRegToString(const struct JRISC_OpReg *reg,
break;

case JRISC_indirect:
assert(!baseIndirect);
ADD_STRING("(r%d)", reg->val.reg);
break;

case JRISC_condition:
assert(!baseIndirect);
switch (reg->val.condition) {
case 0x0: ADD_STRING("T"); /* True/Always */ break;
case 0x1: ADD_STRING("NE"); /* Not Equal */ break;
Expand All @@ -101,24 +110,40 @@ jriscRegToString(const struct JRISC_OpReg *reg,
}
break;

case JRISC_immediate:
// XXX Handle signed/unsigned immediates separately
case JRISC_uimmediate:
if (baseIndirect) {
ADD_STRING("(%s+$%x)", baseIndirect, reg->val.immediate);
ADD_STRING("(%s+%" PRIu8 ")", baseIndirect,
jriscRegUnsignedValue(reg));
} else {
ADD_STRING("#$%x", reg->val.immediate);
ADD_STRING("#%" PRIu8, jriscRegUnsignedValue(reg));
}
break;

case JRISC_zuimmediate:
assert(!baseIndirect);
ADD_STRING("#%" PRIu8, reg->val.uimmediate);
break;

case JRISC_shlimmediate:
assert(!baseIndirect);
ADD_STRING("#%" PRIu8, 32 - jriscRegUnsignedValue(reg));
break;

case JRISC_simmediate:
assert(!baseIndirect);
ADD_STRING("#%" PRId8, reg->val.simmediate);
break;

case JRISC_pcoffset:
// XXX Not really correct without signed immediate values.
ADD_STRING("(pc+%" PRId8 ")", reg->val.immediate);
assert(!baseIndirect);
ADD_STRING("*%+" PRId8, (reg->val.simmediate + 1) * 2);
break;

case JRISC_flag:
// fall through
case JRISC_unused:
// Nothing to do.
assert(!baseIndirect);
visible = false;
break;
}
Expand Down
40 changes: 20 additions & 20 deletions jrisc_optable.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@
/* opName opNum regSrcType regDstType swapRegs cpus */
JRISC_OP(add, 0, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(addc, 1, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(addq, 2, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(addqt, 3, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(addq, 2, JRISC_uimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(addqt, 3, JRISC_uimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(sub, 4, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(subc, 5, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(subq, 6, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(subqt, 7, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(subq, 6, JRISC_uimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(subqt, 7, JRISC_uimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(neg, 8, JRISC_unused, JRISC_reg, false, JRISC_both)
JRISC_OP(and, 9, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(or, 10, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(xor, 11, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(not, 12, JRISC_unused, JRISC_reg, false, JRISC_both)
JRISC_OP(btst, 13, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(bset, 14, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(bclr, 15, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(btst, 13, JRISC_zuimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(bset, 14, JRISC_zuimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(bclr, 15, JRISC_zuimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(mult, 16, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(imult, 17, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(imultn, 18, JRISC_reg, JRISC_reg, false, JRISC_both)
Expand All @@ -45,20 +45,20 @@ JRISC_OP(imacn, 20, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(div, 21, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(abs, 22, JRISC_unused, JRISC_reg, false, JRISC_both)
JRISC_OP(sh, 23, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(shlq, 24, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(shrq, 25, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(shlq, 24, JRISC_shlimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(shrq, 25, JRISC_uimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(sha, 26, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(sharq, 27, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(sharq, 27, JRISC_uimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(ror, 28, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(rorq, 29, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(cmp, 30, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(cmpq, 31, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(rorq, 29, JRISC_uimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(cmp, 30, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(cmpq, 31, JRISC_simmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(sat8, 32, JRISC_unused, JRISC_reg, false, JRISC_gpu)
JRISC_OP(subqmod, 32, JRISC_immediate, JRISC_reg, false, JRISC_dsp)
JRISC_OP(subqmod, 32, JRISC_uimmediate, JRISC_reg, false, JRISC_dsp)
JRISC_OP(sat16, 33, JRISC_unused, JRISC_reg, false, JRISC_gpu)
JRISC_OP(sat16s, 33, JRISC_unused, JRISC_reg, false, JRISC_dsp)
JRISC_OP(move, 34, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(moveq, 35, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(moveq, 35, JRISC_zuimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(moveta, 36, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(movefa, 37, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(movei, 38, JRISC_unused, JRISC_reg, false, JRISC_both)
Expand All @@ -67,15 +67,15 @@ JRISC_OP(loadw, 40, JRISC_indirect, JRISC_reg, false, JRISC_both)
JRISC_OP(load, 41, JRISC_indirect, JRISC_reg, false, JRISC_both)
JRISC_OP(loadp, 42, JRISC_indirect, JRISC_reg, false, JRISC_gpu)
JRISC_OP(sat32s, 42, JRISC_unused, JRISC_reg, false, JRISC_dsp)
JRISC_OP(loadr14n, 43, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(loadr15n, 44, JRISC_immediate, JRISC_reg, false, JRISC_both)
JRISC_OP(loadr14n, 43, JRISC_uimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(loadr15n, 44, JRISC_uimmediate, JRISC_reg, false, JRISC_both)
JRISC_OP(storeb, 45, JRISC_indirect, JRISC_reg, true, JRISC_both)
JRISC_OP(storew, 46, JRISC_indirect, JRISC_reg, true, JRISC_both)
JRISC_OP(store, 47, JRISC_indirect, JRISC_reg, true, JRISC_both)
JRISC_OP(storep, 48, JRISC_indirect, JRISC_reg, true, JRISC_gpu)
JRISC_OP(mirror, 48, JRISC_reg, JRISC_reg, true, JRISC_dsp)
JRISC_OP(storer14n, 49, JRISC_immediate, JRISC_reg, true, JRISC_both)
JRISC_OP(storer15n, 50, JRISC_immediate, JRISC_reg, true, JRISC_both)
JRISC_OP(storer14n, 49, JRISC_uimmediate, JRISC_reg, true, JRISC_both)
JRISC_OP(storer15n, 50, JRISC_uimmediate, JRISC_reg, true, JRISC_both)
JRISC_OP(movepc, 51, JRISC_unused, JRISC_reg, true, JRISC_reg)
JRISC_OP(jump, 52, JRISC_indirect, JRISC_condition,true, JRISC_both)
JRISC_OP(jr, 53, JRISC_pcoffset, JRISC_condition,true, JRISC_both)
Expand All @@ -88,6 +88,6 @@ JRISC_OP(loadr15r, 59, JRISC_reg, JRISC_reg, false, JRISC_both)
JRISC_OP(storer14r, 60, JRISC_reg, JRISC_reg, true, JRISC_both)
JRISC_OP(storer15r, 61, JRISC_reg, JRISC_reg, true, JRISC_both)
JRISC_OP(sat24, 62, JRISC_unused, JRISC_reg, false, JRISC_gpu)
JRISC_OP(addqmod, 63, JRISC_immediate, JRISC_reg, false, JRISC_dsp)
JRISC_OP(addqmod, 63, JRISC_uimmediate, JRISC_reg, false, JRISC_dsp)
JRISC_OP(pack, 63, JRISC_flag, JRISC_reg, false, JRISC_gpu)
JRISC_OP(unpack, 63, JRISC_flag, JRISC_reg, false, JRISC_gpu)
5 changes: 4 additions & 1 deletion jrisc_regtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ enum JRISC_RegType {
JRISC_reg,
JRISC_indirect,
JRISC_condition,
JRISC_immediate,
JRISC_simmediate, /* Signed immediate [-16,+15] */
JRISC_uimmediate, /* Unsigned immedaite [1,32] */
JRISC_zuimmediate, /* Unsigned immedaite [0,31] */
JRISC_shlimmediate, /* Unsigned immediate 32-[0,31] */
JRISC_pcoffset,
JRISC_flag,
JRISC_unused,
Expand Down
10 changes: 10 additions & 0 deletions test/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.PHONY: all
all: test.bin
awk '/\t/' test.s > test.raw.s
../jdis test.bin > test.disassembled.s
diff -u test.raw.s test.disassembled.s
rm test.raw.s test.disassembled.s

test.bin: test.s
rmac -fr $< -o $@

Binary file added test/test.bin
Binary file not shown.
35 changes: 35 additions & 0 deletions test/test.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.org $4000
.text
.gpu
.org $f10000
label:
; Jump to label:
jr T, *+0
nop
jr T, *+4
nop
jump T, (r2)
nop
add r1, r2
addq #5, r2
abs r3
store r3, (r14)
store r3, (r14+8)
store r3, (r15+r8)
moveq #31, r31
moveq #15, r31
moveq #0, r28
rorq #32, r0
rorq #1, r0
shrq #2, r0
shlq #2, r0
sharq #2, r0
sharq #32, r0
sharq #1, r0
cmpq #8, r1
cmpq #-16, r1
cmpq #15, r1
cmpq #0, r1
pack r5
unpack r5
.end

0 comments on commit 553a65a

Please sign in to comment.