From 7ae888b7542690fe21924c3e2339700dfbb41ed0 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 22 Oct 2016 10:48:22 +0200 Subject: [PATCH] Hacky workaround the way the Modula-2 compiler generates non-standard sized loads and saves. More opcodes; simplified table using macros. --- mach/powerpc/mcg/table | 111 ++++++++++++++++------------------- mach/proto/mcg/treebuilder.c | 50 ++++++++++++++-- util/mcgg/build.lua | 8 ++- util/mcgg/ir.dat | 1 + 4 files changed, 102 insertions(+), 68 deletions(-) diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index 632a47ef8..15a278e16 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -463,19 +463,29 @@ PATTERNS /* ALU operations */ - out:(int)reg = ADD4(left:(int)reg, right:(int)reg) - emit "add %out, %left, %right" - cost 4; + #define ALUR(name, instr) \ + out:(int)reg = name(left:(int)reg, right:(int)reg) \ + emit instr " %out, %left, %right" \ + cost 4; \ - out:(int)reg = ADD4(left:(int)reg, right:CONST4) - when signed_constant(%right, 16) - emit "addi %out, %left, $right" - cost 4; + #define ALUC(name, instr) \ + out:(int)reg = name(left:(int)reg, right:CONST4) \ + when signed_constant(%right, 16) \ + emit instr " %out, %left, $right" \ + cost 4; \ - out:(int)reg = ADD4(left:CONST4, right:(int)reg) - when signed_constant(%left, 16) - emit "addi %out, %right, $left" - cost 4; + #define ALUC_reversed(name, instr) \ + out:(int)reg = name(left:CONST4, right:(int)reg) \ + when signed_constant(%left, 16) \ + 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) emit "subf %out, %left, %right" @@ -485,51 +495,32 @@ PATTERNS emit "addi %out, %left, -[$right]" 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) emit "divw %out, %left, %right" emit "mullw %out, %out, %right" emit "subf %out, %out, %left" cost 12; - out:(int)reg = MUL4(left:(int)reg, right:(int)reg) - emit "mullw %out, %left, %right" - cost 4; + ALUR(MUL4, "mullw") + ALUCC(MUL4, "mulli") - out:(int)reg = DIV4(left:(int)reg, right:(int)reg) - emit "divw %out, %left, %right" - cost 4; + ALUR(DIV4, "divw") + ALUR(DIVU4, "divwu") - out:(int)reg = ASL4(left:(int)reg, right:(int)reg) - emit "slw %out, %left, %right" - cost 4; + ALUR(ASL4, "slw") out:(int)reg = NEG4(left:(int)reg) emit "neg %out, %left" cost 4; - out:(int)reg = AND4(left:CONST4, right:(int)reg) - emit "andi. %out, %right, $left" - cost 4; + ALUR(AND4, "and") + ALUCC(AND4, "andi.") - out:(int)reg = AND4(left:(int)reg, right:CONST4) - emit "andi. %out, %left, $right" - cost 4; + ALUR(OR4, "or") + ALUCC(OR4, "ori") - out:(int)reg = AND4(left:(int)reg, right:(int)reg) - emit "and %out, %left, %right" - 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; + ALUR(EOR4, "xor") + ALUCC(EOR4, "xori") out:(int)reg = value:LABEL4 emit "la %out, $value" @@ -546,6 +537,16 @@ PATTERNS /* 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) emit "lfs %out, %addr" cost 4; @@ -558,29 +559,17 @@ PATTERNS emit "lfs %out, address-containing-$value" cost 8; - out:(float)reg = ADDF4(left:(float)reg, right:(float)reg) - emit "fadds %out, %left, %right" - cost 4; + FPU4R(ADDF4, "fadds") + FPU8R(ADDF8, "fadd") - out:(double)reg = ADDF8(left:(double)reg, right:(double)reg) - emit "fadd %out, %left, %right" - cost 4; + FPU4R(SUBF4, "fsubs") + FPU8R(SUBF8, "fsub") - out:(float)reg = SUBF4(left:(float)reg, right:(float)reg) - emit "fsubs %out, %left, %right" - cost 4; + FPU4R(MULF4, "fmuls") + FPU8R(MULF8, "fmul") - out:(double)reg = SUBF8(left:(double)reg, right:(double)reg) - emit "fsub %out, %left, %right" - 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; + FPU4R(DIVF4, "fdivs") + FPU8R(DIVF8, "fdiv") out:(float)reg = NEGF4(left:(float)reg) emit "fneg %out, %left" diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 12aa5c2da..4ee49ebba 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -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) { 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_slu: simple_alu2(opcode, value, IR_LSL); 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_ior: simple_alu2(opcode, value, IR_OR); break; @@ -628,13 +642,37 @@ static void insn_ivalue(int opcode, arith value) break; case op_loi: - push( - new_ir1( - IR_LOAD, value, - pop(EM_pointersize) - ) - ); + { + 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( + new_ir1( + IR_LOAD, s, + ptradd(ptr, offset) + ) + ); + + value -= s; + offset += s; + } + + assert(value == 0); break; + } case op_lof: { diff --git a/util/mcgg/build.lua b/util/mcgg/build.lua index 8606755c7..f8055050c 100644 --- a/util/mcgg/build.lua +++ b/util/mcgg/build.lua @@ -65,6 +65,12 @@ definerule("mcgg", error("you must supply exactly one input file") end + local cpptable = cppfile { + name = e.name.."/cpptable", + outleaf = "cpptable", + srcs = e.srcs + } + return normalrule { name = e.name, cwd = e.cwd, @@ -74,7 +80,7 @@ definerule("mcgg", }, ins = { "util/mcgg+mcgg", - e.srcs[1] + cpptable }, commands = { "%{ins[1]} -i %{ins[2]} -o %{outs[1]} -h %{outs[2]}", diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index 93f7b3c79..7fe51ed30 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -30,6 +30,7 @@ S ADD S SUB S MUL S DIV +S DIVU S MOD S NEG