Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
973 lines (964 sloc) 29.3 KB
function_lists:
condition_passed:
brief: Condition Codes
desc: |
TBD
return_type: int
parameters: int
entries:
- name: eq
brief: Equal
suffix: eq
code_name: eq
code: |
int eq(int status) {
return Z(status);
}
- name: ne
brief: Not Equal
suffix: ne
code: |
int ne(int status) {
return !Z(status);
}
- name: cs
brief: Carry Set
desc: Unsigned less
suffix: cs/lo
code: |
int cs(int status) {
return C(status);
}
- name: cc
brief: Carry Clear
desc: Unsigned greater or equal
suffix: cc/hs
code: |
int cc(int status) {
return !C(status);
}
- name: mi
brief: Negative Set
suffix: mi
code: |
int mi(int status) {
return N(status);
}
- name: pl
brief: Negative Clear
suffix: pl
code: |
int pl(int status) {
return !N(status);
}
- name: vs
brief: Overflow Set
suffix: vs
code: |
int vs(int status) {
return V(status);
}
- name: vc
brief: Overflow Clear
suffix: vc
code: |
int vc(int status) {
return !V(status);
}
- name: hi
brief: Unsigned Greater
suffix: hi
code: |
int hi(int status) {
return !C(status) && !Z(status);
}
- name: ls
brief: Unsigned Less or Equal
suffix: ls
code: |
int ls(int status) {
return C(status) || Z(status);
}
- name: ge
brief: Signed Greater or Equal
suffix: ge
code: |
int ge(int status) {
return N(status) == V(status);
}
- name: lt
brief: Signed Less Than
suffix: lt
code: |
int lt(int status) {
return N(status) != V(status);
}
- name: gt
brief: Signed Greater
suffix: gt
code: |
int gt(int status) {
return N(status) == V(status) && !Z(status);
}
- name: le
brief: Signed Less or Equal
suffix: le
code: |
int le(int status) {
return N(status) != V(status) || Z(status);
}
- name: always
brief: Always
code: |
int always(int status) {
return 1;
}
- name: never
brief: Never
suffix: f
code: |
int never(int status) {
return 0;
}
scalar_op:
brief: Scalar Binary Arithmetic/Logical Operations
desc: |
TBD
return_type: void
parameters: int, int32_t, int32_t
entries:
- name: mov
brief: Move
code_name: mov
code: |
void mov(int d, int32_t a, int32_t b) {
set_reg(d, b);
}
- name: cmn
brief: Compare By Addition
code_name: cmn
code: |
void cmn(int d, int32_t a, int32_t b) {
set_reg(sr, (get_reg(sr) & ~0xf) | condition_flags((int64_t)a + b));
}
- name: add
brief: Addition
code_name: add
code: |
void add(int d, int32_t a, int32_t b) {
set_reg(d, a + b);
}
- name: bic
brief: Bit Clear
code_name: bic
code: |
void bic(int d, int32_t a, int32_t b) {
set_reg(d, a & ~b);
}
- name: mul
brief: Multiply
code_name: mul
code: |
void mul(int d, int32_t a, int32_t b) {
set_reg(d, a * b);
}
- name: eor
brief: Exclusive Or
code_name: eor
code: |
void eor(int d, int32_t a, int32_t b) {
set_reg(d, a ^ b);
}
- name: sub
brief: Subtraction
code_name: sub
code: |
void sub(int d, int32_t a, int32_t b) {
set_reg(d, a - b);
}
- name: and
brief: And
code_name: and
code: |
void and(int d, int32_t a, int32_t b) {
set_reg(d, a & b);
}
- name: mvn
brief: Not
code_name: mvn
code: |
void mvn(int d, int32_t a, int32_t b) {
set_reg(d, ~b);
}
- name: ror
brief: Rotate Right
code_name: ror
code: |
void ror(int d, int32_t a, int32_t b) {
set_reg(d, (a >> b) | (a << (32 - b)));
}
- name: cmp
brief: Compare
code_name: cmp
code: |
void cmp(int d, int32_t a, int32_t b) {
set_reg(sr, (get_reg(sr) & ~0xf) | condition_flags((int64_t)a - b));
}
- name: rsb
brief: Reverse Subtract
code_name: rsb
code: |
void rsb(int d, int32_t a, int32_t b) {
set_reg(d, b - a);
}
- name: btst
brief: Bit Test
code_name: btst
code: |
void btst(int d, int32_t a, int32_t b) {
int32_t tmp_sr = get_reg(sr);
tmp_sr &= ~0xf
tmp_sr |= 0xa;
if (a & (1 << b)) {
tmp_sr &= ~0xa;
}
set_reg(sr, tmp_sr);
}
- name: or
brief: Or
code_name: or
code: |
void or(int d, int32_t a, int32_t b) {
set_reg(d, a | b);
}
- name: extu
brief: Mask Leftmost Bits
code_name: extu
code: |
void extu(int d, int32_t a, int32_t b) {
set_reg(d, a & ((1 << b) - 1));
}
- name: max
brief: Maximum
code_name: max
code: |
void max(int d, int32_t a, int32_t b) {
set_reg(d, a > b ? a : b);
}
- name: bset
brief: Bit Set
code_name: bset
code: |
void bset(int d, int32_t a, int32_t b) {
set_reg(d, a | (1 << b));
}
- name: min
brief: Min
code_name: min
code: |
void min(int d, int32_t a, int32_t b) {
set_reg(d, a < b ? a : b);
}
- name: bclr
brief: Bit Clear
code_name: bclr
code: |
void bclr(int d, int32_t a, int32_t b) {
set_reg(d, a & ~(1 << b));
}
- name: adds2
brief: Add Scaled by 2
code_name: adds2
code: |
void adds2(int d, int32_t a, int32_t b) {
set_reg(d, a + b * 2);
}
- name: bchg
brief: Bit Toggle
code_name: bchg
code: |
void bchg(int d, int32_t a, int32_t b) {
set_reg(d, a ^ (1 << b));
}
- name: adds4
brief: Add Scaled by 4
code_name: adds4
code: |
void adds4(int d, int32_t a, int32_t b) {
set_reg(d, a + b * 4);
}
- name: adds8
brief: Add Scaled by 8
code_name: adds8
code: |
void adds8(int d, int32_t a, int32_t b) {
set_reg(d, a + b * 8);
}
- name: adds16
brief: Add Scaled by 16
code_name: adds16
code: |
void adds16(int d, int32_t a, int32_t b) {
set_reg(d, a + b * 16);
}
- name: exts
brief: Sign Extend
code_name: exts
code: |
void exts(int d, int32_t a, int32_t b) {
set_reg(d, sign_extend(a, b + 1));
}
- name: neg
brief: Negate
code_name: neg
code: |
void neg(int d, int32_t a, int32_t b) {
set_reg(d, -b);
}
- name: lsr
brief: Logical Shift Right
code_name: lsr
code: |
void lsr(int d, int32_t a, int32_t b) {
set_reg(d, (uint32_t)a >> b);
}
- name: clz
brief: Count Leading Zeros
code_name: clz
code: |
void clz(int d, int32_t a, int32_t b) {
int length = 0;
/* TODO: what happens if b is 0? */
while (b != 0) {
b = b >> 1;
length++;
}
set_reg(d, 32 - length);
}
- name: lsl
brief: Logical Shift Left
code_name: lsl
code: |
void lsl(int d, int32_t a, int32_t b) {
set_reg(d, a << b);
}
- name: brev
brief: Bit Reverse
code_name: brev
code: |
void brev(int d, int32_t a, int32_t b) {
uint32_t reverse = 0;
int i;
for (i = 0; i < 32; i++) {
reverse = reverse << 1;
reverse |= b & 1;
b = b >> 1;
}
set_reg(d, reverse);
}
- name: asr
brief: Arithmetic Shift Right
code_name: asr
code: |
void asr(int d, int32_t a, int32_t b) {
if (a && 0x80000000) {
set_reg(d, (a >> b) | ~(0xffffffffu >> b));
} else {
set_reg(d, a >> b);
}
}
- name: _abs
brief: Absolute Value
code_name: abs
code: |
void _abs(int d, int32_t a, int32_t b) {
if (b < 0) {
set_reg(d, -b);
} else {
set_reg(d, b);
}
}
float_op:
name: Scalar Floating Point Operations
desc: |
TBD
return_type: void
parameters: int, float, float
entries:
- name: fadd
brief: Add
code_name: fadd
code: |
void fadd(int d, float a, float b) {
set_reg(d, float_to_int(a + b));
}
- name: fsub
brief: Subtract
code_name: fsub
code: |
void fsub(int d, float a, float b) {
set_reg(d, float_to_int(a - b));
}
- name: fmul
brief: Multiply
code_name: fmul
code: |
void fmul(int d, float a, float b) {
set_reg(d, float_to_int(a * b));
}
- name: fdiv
brief: Divide
code_name: fdiv
code: |
void fdiv(int d, float a, float b) {
// TODO: division through 0?
set_reg(d, float_to_int(a / b));
}
- name: fcmp
brief: Compare
code_name: fcmp
code: |
void fcmp(int d, float a, float b) {
float difference = a - b;
uint32_t flags;
/* TODO */
if (difference == 0.0f) {
flags |= 8; /* Z */
}
if (difference < 0.0f) {
flags |= 4; /* N */
}
set_reg(sr, (get_reg(sr) & ~0xf) | flags);
}
- name: _fabs
brief: Absolute Value
code_name: fabs
code: |
void _fabs(int d, float a, float b) {
set_reg(d, float_to_int(fabs(b)));
}
- name: frsb
brief: Reverse Subtract
code_name: frsb
code: |
void frsb(int d, float a, float b) {
set_reg(d, float_to_int(b - 1));
}
- name: _fmax
brief: Maximum
code_name: fmax
code: |
void _fmax(int d, float a, float b) {
set_reg(d, float_to_int(a > b ? a : b));
}
- name: frcp
brief: Reciprocal
code_name: frcp
code: |
void frcp(int d, float a, float b) {
set_reg(d, float_to_int(1.0f / b));
}
- name: frsqrt
brief: Reciprocal Square Root
code_name: frsqrt
code: |
void frsqrt(int d, float a, float b) {
set_reg(d, float_to_int(1.0f / sqrt(b)));
}
- name: fnmul
brief: Negated Multiply
code_name: fnmul
code: |
void fnmul(int d, float a, float b) {
set_reg(d, float_to_int(-(a * b)));
}
- name: _fmin
brief: Minimum
code_name: fmin
code: |
void _fmin(int d, float a, float b) {
set_reg(d, float_to_int(a < b ? a : b));
}
- name: fld0
brief: Load Zero
code_name: fld0
code: |
void fld0(int d, float a, float b) {
set_reg(d, float_to_int(0.0f));
}
- name: fld1
brief: Load One
code_name: fld1
code: |
void fld1(int d, float a, float b) {
set_reg(d, float_to_int(1.0f));
}
- name: flog2
brief: Binary Logarithmic Function log_2(b)
code_name: flog2
code: |
void flog2(int d, float a, float b) {
set_reg(d, float_to_int(pow(2.0, b)));
}
- name: fexp2
brief: Exponential Function 2^b
code_name: fexp2
code: |
void fexp2(int d, float a, float b) {
set_reg(d, float_to_int(log(b) / log(2.0)));
}
vector_op:
name: Vector Binary Arithmetic/Logical Operations
instructions:
# 16-bit instructions
- name: nop
pattern: 0000 0000 0000 0001
- name: wait
pattern: 0000 0000 0000 0010
- name: user
pattern: 0000 0000 0000 0011
- name: enable
pattern: 0000 0000 0000 0100
code: |
set_reg(sr, get_reg(sr) | (1 << 30));
- name: disable
pattern: 0000 0000 0000 0101
code: |
set_reg(sr, get_reg(sr) | ~(1 << 30));
- name: clr
pattern: 0000 0000 0000 0110
code: |
set_reg(sr, get_reg(sr) & ~0x30);
- name: inc
pattern: 0000 0000 0000 0111
code: |
set_reg(sr, ((get_reg(sr) & 0x30) + 0x10) & 0x30);
- name: chg
pattern: 0000 0000 0000 1000
code: |
set_reg(sr, get_reg(sr) ^ 0x20);
- name: dec
pattern: 0000 0000 0000 1001
code: |
set_reg(sr, ((get_reg(sr) & 0x30) - 0x10) & 0x30);
- name: rti
pattern: 0000 0000 0000 1010
code: |
/* the order is important - the second pop() still uses r28! */
uint32_t new_sr = pop();
set_reg(pc, pop());
set_reg(sr, new_sr);
- name: swi Rd
pattern: 0000 0000 001 Rd:5
code: |
interrupt(0x20 + (get_reg(Rd) & 0x31), "swi");
- name: b Rd
pattern: 0000 0000 010 Rd:5
code: |
set_reg(pc, get_reg(Rd));
- name: b Rd
pattern: 0000 0000 011 Rd:5
code: |
set_reg(lr, get_reg(pc) + 2);
set_reg(pc, get_reg(Rd));
- name: tbb Rd
pattern: 0000 0000 100 Rd:5
code: |
error("TBD");
- name: tbb Rd
pattern: 0000 0000 101 Rd:5
code: |
error("TBD");
- name: mov Rd, cpuid
pattern: 0000 0000 111 Rd:5
code: |
// TODO: compute the proper coreid
set_reg(Rd, 0x04000104);
- name: swi imm
pattern: 0000 0001 11 imm:6
code: |
interrupt(0x20 + (imm & 31), "swi");
- name: push
pattern: 0000 001 with_lr:1 1 first:2 count:5
code: |
int first_register[] = {0, 6, 16, 24};
int i;
uint32_t new_sp = get_reg(sp);
if (with_lr) {
count = (count + 1) & 31;
} else {
count = count + 1;
}
new_sp = new_sp - (count + with_lr) * 4;
if (with_lr) {
push(get_reg(lr));
}
for (i = 0; i < count; i++) {
int reg_index = (first_register[first] + i) & 31;
if (reg_index == 25) {
push(new_sp);
} else {
push(get_reg(reg_index));
}
}
- name: pop
pattern: 0000 001 with_pc:1 0 first:2 count:5
code: |
int first_register[] = {0, 6, 16, 24};
int i;
uint32_t next_sp;
if (with_pc) {
count = (count + 1) & 31;
} else {
count = count + 1;
}
next_sp = get_reg(sp);
// TODO: push/pop order?
for (i = count - 1; i >= 0; i--) {
int reg_index = (first_register[first] + i) & 31;
if (reg_index == 31) {
// pc is not popped from the stack!
set_reg(sp, get_reg(sp) + 4);
} else if (reg_index == 25) {
next_sp = pop();
} else {
set_reg(reg_index, pop());
}
}
if (with_pc) {
set_reg(pc, pop());
}
set_reg(sp, next_sp + (count + with_pc) * 4);
- name: ld Rd, offset(sp)
pattern: 0000 010 offset:5 Rd:4
code: |
set_reg(Rd, load(get_reg(sp) + offset * 4, WORD));
- name: st Rd, offset(sp)
pattern: 0000 011 offset:5 Rd:4
code: |
store(get_reg(sp) + offset * 4, WORD, get_reg(Rd));
- name: ld<size> Rd, (Rs)
pattern: 0000 1 format:2 0 Rs:4 Rd:4
code: |
set_reg(Rd, load(get_reg(Rs), format));
- name: st<size> Rd, (Rs)
pattern: 0000 1 format:2 1 Rs:4 Rd:4
code: |
store(get_reg(Rs), format, get_reg(Rd));
- name: lea Rd, 4*imm(sp)
pattern: 0001 0 imm:6 Rd:5
code: |
set_reg(Rd, get_reg(sp) + 4 * sign_extend(imm, 6));
- name: b<cond> offset
pattern: 0001 1 cond:4 offset:7
code: |
if (condition_passed(cond, get_reg(sr))) {
set_reg(pc, get_reg(pc) + sign_extend_7(offset) * 2);
}
- name: ld Rd, 4*imm(Rs)
pattern: 0010 imm:4 Rs:4 Rd:4
code: |
set_reg(Rd, load(get_reg(Rs) + imm * 4, WORD));
- name: st Rd, 4*imm(Rs)
pattern: 0011 imm:4 Rs:4 Rd:4
code: |
store(get_reg(Rs) + sign_extend(imm, 4) * 4, WORD, Rd);
# TODO: What about add+shl?
- name: <op> Rd, Rs
pattern: 010 op:5 Rs:4 Rd:4
code: |
scalar_op(op, Rd, get_reg(Rd), get_reg(Rs));
- name: <op> Rd, imm
pattern: 011 op:4 imm:5 Rd:4
code: |
scalar_op(op * 2, Rd, get_reg(Rd), imm);
# 32-bit branch instructions
- name: addcmpb<cond> Rd, Ra, Rs, 2*offset + pc
pattern: 1000 cond:4 Ra:4 Rd:4 00 Rs:4 offset:10
code: |
set_reg(Rd, get_reg(Rd) + get_reg(Ra));
if (condition_passed(cond, condition_flags((int64_t)get_reg(Rd) - get_reg(Rs)))) {
set_reg(pc, get_reg(pc) + 2 * sign_extend_10(offset));
}
- name: addcmpb<cond> Rd, imm, Rs, 2*offset + pc
pattern: 1000 cond:4 imm:4 Rd:4 01 Rs:4 offset:10
code: |
set_reg(Rd, get_reg(Rd) + sign_extend_4(imm));
if (condition_passed(cond, condition_flags((int64_t)get_reg(Rd) - get_reg(Rs)))) {
set_reg(pc, get_reg(pc) + 2 * sign_extend_10(offset));
}
- name: addcmpb<cond> Rd, Ra, imm, 2*offset + pc
pattern: 1000 cond:4 Ra:4 Rd:4 10 imm:6 offset:8
code: |
set_reg(Rd, get_reg(Rd) + sign_extend_4(imm));
if (condition_passed(cond, condition_flags((int64_t)get_reg(Rd) - imm))) {
set_reg(pc, get_reg(pc) + 2 * sign_extend_8(offset));
}
- name: addcmpb<cond> Rd, imm1, imm2, 2*offset + pc
pattern: 1000 cond:4 imm1:4 Rd:4 11 imm2:6 offset:8
code: |
set_reg(Rd, get_reg(Rd) + sign_extend_4(imm1));
if (condition_passed(cond, condition_flags((int64_t)get_reg(Rd) - imm2))) {
set_reg(pc, get_reg(pc) + 2 * sign_extend_8(offset));
}
- name: b<cond> 2*offset + pc
pattern: 1001 cond:4 0 offset:23
code: |
if (condition_passed(cond, get_reg(sr))) {
set_reg(pc, get_reg(pc) + 2 * sign_extend_23(offset));
}
- name: bl 2*offset + pc
pattern: 1001 offset1:4 1 offset2:23
code: |
set_reg(lr, get_reg(pc) + 4);
set_reg(pc, get_reg(pc) + 2 * ((sign_extend_4(offset1) << 23) | offset2));
# 32-bit load/store instructions
- name: ld<size><cond> Rd, (Ra, Rb)
pattern: 1010 0000 format:2 0 Rd:5 Ra:5 cond:4 00 Rb:5
desc: |
Imagine some text about load with scaled indexed address mode here.
format: ld%s{format}%s{cond} r%i{Rd}, (r%i{Ra}, r%i{Rb})
code: |
if (condition_passed(cond, get_reg(sr))) {
if (Ra == pc) {
/* TODO: this should be a normal interrupt */
error("tried to modifiy pc");
} else {
set_reg(Rd, load(get_reg(Ra) + size(format) * get_reg(Rb), format));
}
}
- name: st<size><cond> Rd, (Ra, Rb)
pattern: 1010 0000 format:2 1 Rd:5 Ra:5 cond:4 00 Rb:5
code: |
if (condition_passed(cond, get_reg(sr))) {
store(get_reg(Ra) + size(format) * get_reg(Rb), format, get_reg(Rd));
}
- name: ld<size><cond> Rd, imm(Ra)
pattern: 1010 0000 format:2 0 Rd:5 Ra:5 cond:4 10 imm:5
code: |
if (condition_passed(cond, get_reg(sr))) {
set_reg(Rd, load(get_reg(Ra) + imm, format));
}
- name: st<size><cond> Rd, imm(Ra)
pattern: 1010 0000 format:2 1 Rd:5 Ra:5 cond:4 10 imm:5
code: |
if (condition_passed(cond, get_reg(sr))) {
store(get_reg(Ra) + imm, format, get_reg(Rd));
}
- name: ld<size> Rd, offset(Rs)
pattern: 1010 001 offset1:1 format:2 0 Rd:5 Rs:5 offset2:11
code: |
set_reg(Rd, load(get_reg(Rs) + ((sign_extend_1(offset1) << 11) | offset2), format));
- name: st<size> Rd, offset(Rs)
pattern: 1010 001 offset1:1 format:2 1 Rd:5 Rs:5 offset2:11
code: |
store(get_reg(Rs) + ((sign_extend_1(offset1) << 11) | offset2), format, get_reg(Rd));
- name: ld<size><cond> Rd, --(Ra)
pattern: 1010 0100 format:2 0 Rd:5 Ra:5 cond:4 000 0000
code: |
if (condition_passed(cond, get_reg(sr))) {
set_reg(Ra, get_reg(Ra) - size(format));
set_reg(Rd, load(get_reg(Ra), format));
}
- name: st<size><cond> Rd, --(Ra)
pattern: 1010 0100 format:2 1 Rd:5 Ra:5 cond:4 000 0000
code: |
if (condition_passed(cond, get_reg(sr))) {
set_reg(Ra, get_reg(Ra) - size(format));
store(get_reg(Ra), format, get_reg(Rd));
}
- name: ld<size><cond> Rd, (Ra)++
pattern: 1010 0101 format:2 0 Rd:5 Ra:5 cond:4 000 0000
code: |
if (condition_passed(cond, get_reg(sr))) {
set_reg(Rd, load(get_reg(Ra), format));
set_reg(Ra, get_reg(Ra) + size(format));
}
- name: st<size><cond> Rd, (Ra)++
pattern: 1010 0101 format:2 1 Rd:5 Ra:5 cond:4 000 0000
code: |
if (condition_passed(cond, get_reg(sr))) {
store(get_reg(Ra), format, get_reg(Rd));
set_reg(Ra, get_reg(Ra) + size(format));
}
- name: ld<size> Rd, offset(Rs)
pattern: 1010 10 base:2 format:2 0 Rd:5 offset:16
code: |
int base_reg[] = {24, 25, 31, 0};
set_reg(Rd, load(get_reg(base_reg[base]) + sign_extend_16(offset), format));
- name: st<size> Rd, offset(Rs)
pattern: 1010 10 base:2 format:2 1 Rd:5 offset:16
code: |
int base_reg[] = {24, 25, 31, 0};
store(get_reg(base_reg[base]) + sign_extend_16(offset), format, get_reg(Rd));
# 32-bit arithmetic instructions
- name: <op> Rd, imm
pattern: 1011 00 op:5 Rd:5 imm:16
code: |
scalar_op(op, Rd, get_reg(Rd), sign_extend_16(imm));
- name: lea Rd, offset(Rs)
pattern: 1011 01 Rs:5 Rd:5 offset:16
code: |
set_reg(Rd, get_reg(Rs) + sign_extend_16(offset));
- name: lea Rd, offset(pc)
pattern: 1011 1111 111 Rd:5 offset:16
code: |
set_reg(Rd, get_reg(pc) + sign_extend_16(offset));
- name: <op><cond> Rd, Ra, Rb
pattern: 1100 00 op:5 Rd:5 Ra:5 cond:4 00 Rb:5
code: |
if (condition_passed(cond, get_reg(sr))) {
scalar_op(op, Rd, get_reg(Ra), get_reg(Rb));
}
- name: <op><cond> Rd, Ra, imm
pattern: 1100 00 op:5 Rd:5 Ra:5 cond:4 1 imm:6
code: |
if (condition_passed(cond, get_reg(sr))) {
scalar_op(op, Rd, get_reg(Ra), sign_extend_6(imm));
}
# mulhd variants
- name: mulhd<u/s><u/s><cond> Rd, Ra, Rb
pattern: 1100 0100 0 unsigned1:1 unsigned2:1 Rd:5 Ra:5 cond:4 00 Rb:5
code: |
if (condition_passed(cond, get_reg(sr))) {
if (unsigned1 && unsigned2) {
set_reg(Rd, (to_uint64(get_reg(Ra)) * to_uint64(get_reg(Rb))) >> 32);
} else if (unsigned1) {
set_reg(Rd, (to_uint64(get_reg(Ra)) * to_int64(get_reg(Rb))) >> 32);
} else if (unsigned2) {
set_reg(Rd, (to_int64(get_reg(Ra)) * to_uint64(get_reg(Rb))) >> 32);
} else {
set_reg(Rd, (to_int64(get_reg(Ra)) * to_int64(get_reg(Rb))) >> 32);
}
}
- name: mulhd<u/s><u/s><cond> Rd, Ra, imm
pattern: 1100 0100 0 unsigned1:1 unsigned2:1 Rd:5 Ra:5 cond:4 1 imm:6
code: |
if (condition_passed(cond, get_reg(sr))) {
if (unsigned1 && unsigned2) {
set_reg(Rd, (to_uint64(get_reg(Ra)) * (to_uint64(sign_extend_6(imm)) & 0xffffffff)) >> 32);
} else if (unsigned1) {
set_reg(Rd, (to_uint64(get_reg(Ra)) * to_int64(sign_extend_6(imm))) >> 32);
} else if (unsigned2) {
set_reg(Rd, (to_int64(get_reg(Ra)) * (to_uint64(sign_extend_6(imm)) & 0xffffffff)) >> 32);
} else {
set_reg(Rd, (to_int64(get_reg(Ra)) * to_int64(sign_extend_6(imm))) >> 32);
}
}
# div variants
- name: div<u/s><u/s><cond> Rd, Ra, Rb
pattern: 1100 0100 1 unsigned1:1 unsigned2:1 Rd:5 Ra:5 cond:4 00 Rb:5
code: |
if (condition_passed(cond, get_reg(sr))) {
if (unsigned1 && unsigned2) {
set_reg(Rd, to_uint64(get_reg(Ra)) / to_uint64(get_reg(Rb)));
} else if (unsigned1) {
set_reg(Rd, to_uint64(get_reg(Ra)) / to_int64(get_reg(Rb)));
} else if (unsigned2) {
set_reg(Rd, to_int64(get_reg(Ra)) / to_uint64(get_reg(Rb)));
} else {
set_reg(Rd, to_int64(get_reg(Ra)) / to_int64(get_reg(Rb)));
}
}
- name: div<u/s><u/s><cond> Rd, Ra, imm
pattern: 1100 0100 1 unsigned1:1 unsigned2:1 Rd:5 Ra:5 cond:4 1 imm:6
code: |
if (condition_passed(cond, get_reg(sr))) {
if (unsigned1 && unsigned2) {
set_reg(Rd, to_uint64(get_reg(Ra)) / sign_extend_6(imm));
} else if (unsigned1) {
set_reg(Rd, to_uint64(get_reg(Ra)) / to_int64(sign_extend_6(imm)));
} else if (unsigned2) {
set_reg(Rd, to_int64(get_reg(Ra)) / sign_extend_6(imm));
} else {
set_reg(Rd, to_int64(get_reg(Ra)) / to_int64(sign_extend_6(imm)));
}
}
- name: add<cond> Rd, Ra, Rb shl 8
pattern: 1100 0101 111 Rd:5 Ra:5 cond:4 00 Rb:5
code: |
if (condition_passed(cond, get_reg(sr))) {
set_reg(Rd, get_reg(Ra) + (get_reg(Rb) << 8));
}
# floating point instructions
- name: <fop><cond> Rd, Ra, Rb
pattern: 1100 100 fop:4 Rd:5 Ra:5 cond:4 00 Rb:5
code: |
if (condition_passed(cond, get_reg(sr))) {
float_op(fop, Rd, int_to_float(get_reg(Ra)), int_to_float(get_reg(Rb)));
}
- name: <fop><cond> Rd, Ra, imm
pattern: 1100 100 fop:4 Rd:5 Ra:5 cond:4 1 imm:6
code: |
if (condition_passed(cond, get_reg(sr))) {
uint32_t b = 0;
if (imm & 0x20) {
b |= 0x80000000;
}
int exponent = (imm >> 2) & 0x7;
if (exponent != 0) {
b |= (exponent + 124) << 23;
int mantissa = imm & 0x3;
b |= mantissa << 21;
}
float_op(fop, Rd, int_to_float(get_reg(Ra)), int_to_float(b));
}
- name: ftrunc<cond> Rd, Ra, lsl imm
pattern: 1100 1010 000 Rd:5 Ra:5 cond:4 1 imm:6
code: |
if (condition_passed(cond, get_reg(sr))) {
float shift = pow(2, sign_extend_6(imm));
set_reg(Rd, (int32_t)(int_to_float(get_reg(Ra)) * shift));
}
- name: floor<cond> Rd, Ra, lsl imm
pattern: 1100 1010 001 Rd:5 Ra:5 cond:4 1 imm:6
code: |
if (condition_passed(cond, get_reg(sr))) {
float shift = pow(2, sign_extend_6(imm));
set_reg(Rd, (int32_t)floor(int_to_float(get_reg(Ra)) * shift));
}
- name: flts<cond> Rd, Ra, lsr imm
pattern: 1100 1010 010 Rd:5 Ra:5 cond:4 1 imm:6
code: |
if (condition_passed(cond, get_reg(sr))) {
float shift = pow(2, sign_extend_6(imm));
float result = (int32_t)get_reg(Ra);
set_reg(Rd, float_to_int(result / shift));
}
- name: fltu<cond> Rd, Ra, lsr imm
pattern: 1100 1010 011 Rd:5 Ra:5 cond:4 1 imm:6
code: |
if (condition_passed(cond, get_reg(sr))) {
float shift = pow(2, sign_extend_6(imm));
float result = (uint32_t)get_reg(Ra);
set_reg(Rd, float_to_int(result / shift));
}
# 48-bit scalar instructions
- name: lea Rd, offset(pc)
pattern: 1110 0101 000 Rd:5 offset1:16 offset2:16
code: |
set_reg(Rd, get_reg(pc) + (offset2 << 16) + offset1);
- name: ld Rd, offset(Rs)
pattern: 1110 0110 format:2 0 Rd:5 offset1:16 Rs:5 offset2:11
code: |
set_reg(Rd, load(get_reg(Rs) + (offset2 << 16) + offset1, format));
- name: st Rd, offset(Rs)
pattern: 1110 0110 format:2 1 Rd:5 offset1:16 Rs:5 offset2:11
code: |
store(get_reg(Rs) + (offset2 << 16) + offset1, format, get_reg(Rd));
- name: ld Rd, offset(Rs)
pattern: 1110 0111 format:2 0 Rd:5 offset1:16 11111 offset2:11
code: |
set_reg(Rd, load(get_reg(pc) + (offset2 << 16) + offset1, format));
- name: st Rd, offset(Rs)
pattern: 1110 0111 format:2 1 Rd:5 offset1:16 11111 offset2:11
code: |
store(get_reg(pc) + (offset2 << 16) + offset1, format, get_reg(Rd));
- name: <op> Rd, imm
pattern: 1110 10 op:5 Rd:5 imm1:16 imm2:16
code: |
scalar_op(op, Rd, get_reg(Rd), (imm2 << 16) | imm1);
- name: add Rd, Rs, imm
pattern: 1110 11 Rs:5 Rd:5 imm1:16 imm2:16
code: |
set_reg(Rd, get_reg(Rs) + ((imm2 << 16) | imm1));