Hacky workaround the way the Modula-2 compiler generates non-standard sized

loads and saves. More opcodes; simplified table using macros.
This commit is contained in:
David Given 2016-10-22 10:48:22 +02:00
parent 90d0661639
commit 7ae888b754
4 changed files with 102 additions and 68 deletions

View file

@ -463,19 +463,29 @@ PATTERNS
/* ALU operations */ /* ALU operations */
out:(int)reg = ADD4(left:(int)reg, right:(int)reg) #define ALUR(name, instr) \
emit "add %out, %left, %right" out:(int)reg = name(left:(int)reg, right:(int)reg) \
cost 4; emit instr " %out, %left, %right" \
cost 4; \
out:(int)reg = ADD4(left:(int)reg, right:CONST4) #define ALUC(name, instr) \
when signed_constant(%right, 16) out:(int)reg = name(left:(int)reg, right:CONST4) \
emit "addi %out, %left, $right" when signed_constant(%right, 16) \
cost 4; emit instr " %out, %left, $right" \
cost 4; \
out:(int)reg = ADD4(left:CONST4, right:(int)reg) #define ALUC_reversed(name, instr) \
when signed_constant(%left, 16) out:(int)reg = name(left:CONST4, right:(int)reg) \
emit "addi %out, %right, $left" when signed_constant(%left, 16) \
cost 4; emit instr " %out, %right, $left" \
cost 4; \
#define ALUCC(name, instr) \
ALUC(name, instr) \
ALUC_reversed(name, instr)
ALUR(ADD4, "add")
ALUCC(ADD4, "addi")
out:(int)reg = SUB4(left:(int)reg, right:(int)reg) out:(int)reg = SUB4(left:(int)reg, right:(int)reg)
emit "subf %out, %left, %right" emit "subf %out, %left, %right"
@ -485,51 +495,32 @@ PATTERNS
emit "addi %out, %left, -[$right]" emit "addi %out, %left, -[$right]"
cost 4; cost 4;
out:(int)reg = MUL4(left:(int)reg, right:(int)reg)
emit "mullw %out, %right, %left"
cost 4;
out:(int)reg = MOD4(left:(int)reg, right:(int)reg) out:(int)reg = MOD4(left:(int)reg, right:(int)reg)
emit "divw %out, %left, %right" emit "divw %out, %left, %right"
emit "mullw %out, %out, %right" emit "mullw %out, %out, %right"
emit "subf %out, %out, %left" emit "subf %out, %out, %left"
cost 12; cost 12;
out:(int)reg = MUL4(left:(int)reg, right:(int)reg) ALUR(MUL4, "mullw")
emit "mullw %out, %left, %right" ALUCC(MUL4, "mulli")
cost 4;
out:(int)reg = DIV4(left:(int)reg, right:(int)reg) ALUR(DIV4, "divw")
emit "divw %out, %left, %right" ALUR(DIVU4, "divwu")
cost 4;
out:(int)reg = ASL4(left:(int)reg, right:(int)reg) ALUR(ASL4, "slw")
emit "slw %out, %left, %right"
cost 4;
out:(int)reg = NEG4(left:(int)reg) out:(int)reg = NEG4(left:(int)reg)
emit "neg %out, %left" emit "neg %out, %left"
cost 4; cost 4;
out:(int)reg = AND4(left:CONST4, right:(int)reg) ALUR(AND4, "and")
emit "andi. %out, %right, $left" ALUCC(AND4, "andi.")
cost 4;
out:(int)reg = AND4(left:(int)reg, right:CONST4) ALUR(OR4, "or")
emit "andi. %out, %left, $right" ALUCC(OR4, "ori")
cost 4;
out:(int)reg = AND4(left:(int)reg, right:(int)reg) ALUR(EOR4, "xor")
emit "and %out, %left, %right" ALUCC(EOR4, "xori")
cost 4;
out:(int)reg = OR4(left:(int)reg, right:(int)reg)
emit "or %out, %right, %left"
cost 4;
out:(int)reg = EOR4(left:(int)reg, right:(int)reg)
emit "xor %out, %right, %left"
cost 4;
out:(int)reg = value:LABEL4 out:(int)reg = value:LABEL4
emit "la %out, $value" emit "la %out, $value"
@ -546,6 +537,16 @@ PATTERNS
/* FPU operations */ /* FPU operations */
#define FPU4R(name, instr) \
out:(float)reg = name(left:(float)reg, right:(float)reg) \
emit instr " %out, %left, %right" \
cost 4; \
#define FPU8R(name, instr) \
out:(double)reg = name(left:(double)reg, right:(double)reg) \
emit instr " %out, %left, %right" \
cost 4; \
out:(float)reg = LOADF4(addr:address) out:(float)reg = LOADF4(addr:address)
emit "lfs %out, %addr" emit "lfs %out, %addr"
cost 4; cost 4;
@ -558,29 +559,17 @@ PATTERNS
emit "lfs %out, address-containing-$value" emit "lfs %out, address-containing-$value"
cost 8; cost 8;
out:(float)reg = ADDF4(left:(float)reg, right:(float)reg) FPU4R(ADDF4, "fadds")
emit "fadds %out, %left, %right" FPU8R(ADDF8, "fadd")
cost 4;
out:(double)reg = ADDF8(left:(double)reg, right:(double)reg) FPU4R(SUBF4, "fsubs")
emit "fadd %out, %left, %right" FPU8R(SUBF8, "fsub")
cost 4;
out:(float)reg = SUBF4(left:(float)reg, right:(float)reg) FPU4R(MULF4, "fmuls")
emit "fsubs %out, %left, %right" FPU8R(MULF8, "fmul")
cost 4;
out:(double)reg = SUBF8(left:(double)reg, right:(double)reg) FPU4R(DIVF4, "fdivs")
emit "fsub %out, %left, %right" FPU8R(DIVF8, "fdiv")
cost 4;
out:(float)reg = MULF4(left:(float)reg, right:(float)reg)
emit "fmuls %out, %left, %right"
cost 4;
out:(double)reg = MULF8(left:(double)reg, right:(double)reg)
emit "fmul %out, %left, %right"
cost 4;
out:(float)reg = NEGF4(left:(float)reg) out:(float)reg = NEGF4(left:(float)reg)
emit "fneg %out, %left" emit "fneg %out, %left"

View file

@ -458,6 +458,19 @@ static void change_by(struct ir* address, int amount)
); );
} }
static struct ir* ptradd(struct ir* address, int offset)
{
if (offset == 0)
return address;
return
new_ir2(
IR_ADD, EM_pointersize,
address,
new_wordir(offset)
);
}
static void insn_ivalue(int opcode, arith value) static void insn_ivalue(int opcode, arith value)
{ {
switch (opcode) switch (opcode)
@ -476,6 +489,7 @@ static void insn_ivalue(int opcode, arith value)
case op_mlu: simple_alu2(opcode, value, IR_MUL); break; case op_mlu: simple_alu2(opcode, value, IR_MUL); break;
case op_slu: simple_alu2(opcode, value, IR_LSL); break; case op_slu: simple_alu2(opcode, value, IR_LSL); break;
case op_sru: simple_alu2(opcode, value, IR_LSR); break; case op_sru: simple_alu2(opcode, value, IR_LSR); break;
case op_dvu: simple_alu2(opcode, value, IR_DIVU); break;
case op_and: simple_alu2(opcode, value, IR_AND); break; case op_and: simple_alu2(opcode, value, IR_AND); break;
case op_ior: simple_alu2(opcode, value, IR_OR); break; case op_ior: simple_alu2(opcode, value, IR_OR); break;
@ -628,13 +642,37 @@ static void insn_ivalue(int opcode, arith value)
break; break;
case op_loi: case op_loi:
{
struct ir* ptr = pop(EM_pointersize);
int offset = 0;
/* FIXME: this is awful; need a better way of dealing with
* non-standard EM sizes. */
if (value > (EM_wordsize*2))
appendir(ptr);
while (value > 0)
{
int s;
if (value > (EM_wordsize*2))
s = EM_wordsize*2;
else
s = value;
push( push(
new_ir1( new_ir1(
IR_LOAD, value, IR_LOAD, s,
pop(EM_pointersize) ptradd(ptr, offset)
) )
); );
value -= s;
offset += s;
}
assert(value == 0);
break; break;
}
case op_lof: case op_lof:
{ {

View file

@ -65,6 +65,12 @@ definerule("mcgg",
error("you must supply exactly one input file") error("you must supply exactly one input file")
end end
local cpptable = cppfile {
name = e.name.."/cpptable",
outleaf = "cpptable",
srcs = e.srcs
}
return normalrule { return normalrule {
name = e.name, name = e.name,
cwd = e.cwd, cwd = e.cwd,
@ -74,7 +80,7 @@ definerule("mcgg",
}, },
ins = { ins = {
"util/mcgg+mcgg", "util/mcgg+mcgg",
e.srcs[1] cpptable
}, },
commands = { commands = {
"%{ins[1]} -i %{ins[2]} -o %{outs[1]} -h %{outs[2]}", "%{ins[1]} -i %{ins[2]} -o %{outs[1]} -h %{outs[2]}",

View file

@ -30,6 +30,7 @@ S ADD
S SUB S SUB
S MUL S MUL
S DIV S DIV
S DIVU
S MOD S MOD
S NEG S NEG