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:
parent
90d0661639
commit
7ae888b754
|
@ -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"
|
||||||
|
|
|
@ -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:
|
||||||
{
|
{
|
||||||
|
|
|
@ -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]}",
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue