multiplication

This commit is contained in:
uosfz 2026-06-19 14:31:51 +02:00
parent 12efe0056b
commit d87b2fed28
Signed by: uosfz
SSH key fingerprint: SHA256:FlktuluyhTQg3jHZNLKwxOOC5hbfrUXM0tz3IA3lGJo
3 changed files with 18 additions and 19 deletions

View file

@ -13,6 +13,8 @@ enum op {
ADDI, // ra += imm
SUB, // ra -= rb
SUBI, // ra -= imm
MUL, // ra *= rb
MULI, // ra *= imm
NEG, // ra = -ra (= ~ra + 1) (rb not used!)
NOT, // ra = ~ra (rb not used!)
MOV, // ra = rb
@ -72,6 +74,8 @@ enum reg {
#define GEN_ADDI(my_ra, i) ((struct insn) { .op = ADDI, .ra = my_ra, .rb = 0, .imm = i })
#define GEN_SUB(my_ra, my_rb) ((struct insn) { .op = SUB, .ra = my_ra, .rb = my_rb })
#define GEN_SUBI(my_ra, i) ((struct insn) { .op = SUBI, .ra = my_ra, .rb = 0, .imm = i })
#define GEN_MUL(my_ra, my_rb) ((struct insn) { .op = MUL, .ra = my_ra, .rb = my_rb })
#define GEN_MULI(my_ra, i) ((struct insn) { .op = MULI, .ra = my_ra, .rb = 0, .imm = i })
#define GEN_NEG(my_ra) ((struct insn) { .op = NEG, .ra = my_ra, .rb = 0 })
#define GEN_NOT(my_ra) ((struct insn) { .op = NOT, .ra = my_ra, .rb = 0 })
#define GEN_ANDI(my_ra, i) ((struct insn) { .op = ANDI, .ra = my_ra, .rb = 0, .imm = i })

View file

@ -36,25 +36,8 @@ static void app_jitpaint_step(void *self) {
// input: R0: x, R1: y, R2: t
// output: R0: r, R1: g, R2: b
struct insn insns[] = {
GEN_ADD(R0, R2),
GEN_SUB(R1, R2),
GEN_SRLI(R0, 3),
GEN_SRLI(R1, 3),
GEN_ADD(R0, R1),
GEN_ANDI(R0, 1),
GEN_MOV(R1, R0),
GEN_SLLI(R1, 1),
GEN_OR(R0, R1),
GEN_MOV(R1, R0),
GEN_SLLI(R1, 2),
GEN_OR(R0, R1),
GEN_MOV(R1, R0),
GEN_SLLI(R1, 4),
GEN_OR(R0, R1),
GEN_MUL(R0, R1),
GEN_SRLI(R0, 8),
GEN_MOV(R1, R0),
GEN_MOV(R2, R0),

View file

@ -98,6 +98,18 @@ uint8_t *jit_compile_single(struct insn *insn, uint8_t *mem) {
mem = jit_compile_single(&help, mem);
}
break;
case MUL:
*mem++ = OPBYTE(0x48, x86a, x86b);
*mem++ = 0x0f;
*mem++ = 0xaf;
*mem++ = MODRM(0xc0, x86a, x86b);
break;
case MULI:
// using same register twice because we do in-place
*mem++ = OPBYTE(0x48, x86a, x86a);
*mem++ = 69;
*mem++ = MODRM(0xc0, x86a, x86a);
break;
case ANDI:
// This is the worst case, when the operand has to be 8 bytes big. There are way better encodings. the insn also sign-extends.
help = GEN_MOVI(RSCRATCH, insn->imm);