summaryrefslogtreecommitdiff
path: root/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
committerAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
commit094b96ca1df4a035b5f93c351f773306c0241f3f (patch)
tree95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-main.tar.gz
MWCC-main.zip
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c')
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c345
1 files changed, 345 insertions, 0 deletions
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c
new file mode 100644
index 0000000..b1f8ffb
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c
@@ -0,0 +1,345 @@
+#include "compiler/PCodeUtilities.h"
+#include "compiler/CError.h"
+#include "compiler/CFunc.h"
+#include "compiler/CParser.h"
+#include "compiler/CodeGen.h"
+#include "compiler/Exceptions.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/Registers.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+
+void pcsetrecordbit(PCode *pc) {
+ int reg;
+ PCodeArg *arg;
+ short argCount;
+ int argIdx;
+
+ pc->flags &= ~(fIsMove | fCommutative | fIsCSE);
+ if ((pc->flags & fOpTypeMask) == fOpTypeFPR) {
+ reg = 1;
+ } else if ((pc->flags & fOpTypeMask) == fOpTypeVR) {
+ reg = 6;
+ } else {
+ reg = 0;
+ }
+
+ if (pc->op == PC_ANDI || pc->op == PC_ANDIS) {
+ pc->flags |= fRecordBit;
+ } else if (pc->op == PC_ADDI || pc->op == PC_ADDIC) {
+ pc->flags |= fSetsCarry;
+ pc->flags |= fRecordBit;
+ change_num_operands(pc, 5);
+ pc->op = PC_ADDICR;
+
+ CError_ASSERT(76, pc->args[3].kind == PCOp_PLACEHOLDEROPERAND);
+ pc->args[3].kind = PCOp_REGISTER;
+ pc->args[3].arg = RegClass_SPR;
+ pc->args[3].data.reg.reg = 0;
+ pc->args[3].data.reg.effect = EffectWrite;
+ CError_ASSERT(80, pc->args[4].kind == PCOp_PLACEHOLDEROPERAND);
+ pc->args[4].kind = PCOp_REGISTER;
+ pc->args[4].arg = RegClass_CRFIELD;
+ pc->args[4].data.reg.reg = reg;
+ pc->args[4].data.reg.effect = EffectWrite;
+ } else {
+ arg = pc->args;
+ argIdx = argCount = pc->argCount;
+ while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) {
+ if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_CRFIELD && arg->data.reg.reg == reg) {
+ arg->data.reg.effect |= EffectWrite;
+ pc->flags |= fRecordBit;
+ return;
+ }
+ arg++;
+ argIdx--;
+ }
+
+ if (argIdx <= 0) {
+ arg = &pc->args[argCount];
+ pc->argCount++;
+ }
+
+ CError_ASSERT(105, arg->kind == PCOp_PLACEHOLDEROPERAND);
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_CRFIELD;
+ arg->data.reg.reg = reg;
+ arg->data.reg.effect = EffectWrite;
+ if (pc->op != PC_ADDICR)
+ pc->flags |= fRecordBit;
+ }
+}
+
+void pcsetsideeffects(PCode *pc) {
+ pc->flags &= ~(fIsMove | fCommutative | fIsCSE);
+ pc->flags |= fSideEffects;
+}
+
+void pcsetlinkbit(PCode *pc) {
+ PCodeArg *arg;
+ int argIdx;
+
+ switch (pc->op) {
+ case PC_B:
+ pc->op = PC_BL;
+ break;
+ case PC_BCTR:
+ pc->op = PC_BCTRL;
+ break;
+ case PC_BLR:
+ pc->op = PC_BLRL;
+ break;
+ }
+
+ arg = pc->args;
+ argIdx = pc->argCount;
+ while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) {
+ if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_SPR && arg->data.reg.reg == 1) {
+ arg->data.reg.effect |= EffectWrite;
+ pc->flags |= fLink;
+ return;
+ }
+ arg++;
+ argIdx--;
+ }
+
+ CError_ASSERT(169, arg->kind == PCOp_PLACEHOLDEROPERAND);
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = 1;
+ arg->data.reg.effect = EffectWrite;
+
+ if (opcodeinfo[pc->op].flags & fIsCall) {
+ pc->flags &= ~fIsBranch;
+ pc->flags |= fIsCall;
+ }
+ pc->flags |= fLink;
+}
+
+void branch_label(PCodeLabel *label) {
+ if (pclastblock->pcodeCount) {
+ pcbranch(pclastblock, label);
+ makepcblock();
+ }
+ pclabel(pclastblock, label);
+}
+
+void branch_conditional(short a, short compareop, short c, PCodeLabel *label) {
+ PCodeBlock *tmpblock;
+ PCodeLabel *tmplabel;
+ int r28;
+
+ tmpblock = pclastblock;
+ tmplabel = makepclabel();
+
+ switch (compareop) {
+ case ENOTEQU:
+ c = !c;
+ case EEQU:
+ r28 = 2;
+ break;
+ case EGREATEREQU:
+ c = !c;
+ case ELESS:
+ r28 = 0;
+ break;
+ case ELESSEQU:
+ c = !c;
+ case EGREATER:
+ r28 = 1;
+ break;
+ }
+
+ emitpcode(c ? PC_BT : PC_BF, a, r28, label);
+ pcbranch(pclastblock, label);
+ pcbranch(pclastblock, tmplabel);
+ makepcblock();
+ pclabel(pclastblock, tmplabel);
+}
+
+void branch_always(PCodeLabel *label) {
+ emitpcode(PC_B, label);
+ pcbranch(pclastblock, label);
+ makepcblock();
+}
+
+void branch_decrement_always(Opcode opcode, PCodeLabel *label) {
+ PCodeLabel *tmplabel = makepclabel();
+ emitpcode(opcode, label);
+ pcbranch(pclastblock, label);
+ pcbranch(pclastblock, tmplabel);
+ makepcblock();
+ pclabel(pclastblock, tmplabel);
+}
+
+void branch_indirect(Object *obj) {
+ emitpcode(PC_BCTR, obj, 0);
+ makepcblock();
+}
+
+int branch_count_volatiles(void) {
+ int count = 0;
+ int i;
+ RegClass rclass;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ for (i = 0; i < n_scratch_registers[rclass]; i++) {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+PCodeArg *branch_record_volatiles(PCodeArg *arglist, UInt32 *masks) {
+ int i;
+ RegClass rclass;
+
+ for (rclass = RegClassMax - 1; rclass >= 0; rclass--) {
+ for (i = 0; i < n_scratch_registers[rclass]; i++) {
+ arglist->kind = PCOp_REGISTER;
+ arglist->arg = rclass;
+ arglist->data.reg.reg = scratch_registers[rclass][i];
+ arglist->data.reg.effect = EffectWrite;
+ if (masks[rclass] & (1 << scratch_registers[rclass][i]))
+ arglist->data.reg.effect |= EffectRead;
+ arglist++;
+ }
+ }
+
+ return arglist;
+}
+
+void branch_subroutine(Object *obj, short add_nop, UInt32 *masks) {
+ int count;
+ PCode *pc;
+ PCodeArg *arg;
+
+ count = branch_count_volatiles();
+ if (copts.exceptions && current_statement)
+ count += countexceptionactionregisters(current_statement->dobjstack);
+
+ pc = makepcode(PC_BL, count, obj, 0);
+ arg = branch_record_volatiles(pc->args + 1, masks);
+ if (copts.exceptions && current_statement)
+ noteexceptionactionregisters(current_statement->dobjstack, arg);
+ appendpcode(pclastblock, pc);
+
+ if (add_nop)
+ emitpcode(PC_NOP);
+
+ branch_label(makepclabel());
+ if (copts.exceptions && current_statement)
+ recordexceptionactions(pc, current_statement->dobjstack);
+}
+
+void branch_subroutine_ctr(UInt32 *masks) {
+ int count;
+ PCode *pc;
+ PCodeArg *arg;
+
+ count = branch_count_volatiles();
+ if (copts.exceptions && current_statement)
+ count += countexceptionactionregisters(current_statement->dobjstack);
+
+ pc = makepcode(PC_BCTRL, count);
+ arg = branch_record_volatiles(pc->args + 1, masks);
+ if (copts.exceptions && current_statement)
+ noteexceptionactionregisters(current_statement->dobjstack, arg);
+ appendpcode(pclastblock, pc);
+
+ branch_label(makepclabel());
+ if (copts.exceptions && current_statement)
+ recordexceptionactions(pc, current_statement->dobjstack);
+}
+
+void add_immediate(short dest_reg, short base_reg, Object *obj, SInt16 offset) {
+ short tmp_reg = base_reg;
+
+ if (obj && offset && obj->datatype != DLOCAL) {
+ tmp_reg = used_virtual_registers[RegClass_GPR]++;
+ add_immediate_lo(tmp_reg, base_reg, obj, 0, 1);
+ obj = NULL;
+ }
+
+ if (!obj && !offset)
+ emitpcode(PC_MR, dest_reg, tmp_reg);
+ else
+ emitpcode(PC_ADDI, dest_reg, tmp_reg, obj, offset);
+}
+
+PCode *add_immediate_lo(short dest_reg, short base_reg, Object *obj, SInt16 offset, char add_to_block) {
+ PCode *pc;
+
+ CError_ASSERT(577, obj);
+
+ pc = makepcode(PC_ADDI, dest_reg, base_reg, obj, offset);
+ if (add_to_block)
+ appendpcode(pclastblock, pc);
+ return pc;
+}
+
+PCode *op_absolute_ha(short dest_reg, short base_reg, Object *obj, short offset, char add_to_block) {
+ PCode *pc;
+ int tmp_reg;
+
+ if (obj->datatype == DLOCAL) {
+ pc = makepcode(PC_ADDIS, dest_reg, base_reg, obj, offset);
+ } else if (copts.codegen_pic) {
+ tmp_reg = base_reg;
+ CError_ASSERT(601, tmp_reg);
+ pc = makepcode(PC_ADDIS, dest_reg, tmp_reg, obj, offset);
+ } else {
+ CError_ASSERT(606, base_reg == 0);
+ pc = makepcode(PC_LIS, dest_reg, obj, offset);
+ }
+
+ if (add_to_block)
+ appendpcode(pclastblock, pc);
+ return pc;
+}
+
+void load_store_register(Opcode opcode, short dest_reg, short base_reg, Object *obj, SInt32 offset) {
+ short addi_tmp;
+ short offset_reg1;
+ short offset_reg2;
+
+ offset_reg1 = base_reg;
+ if (obj && offset && obj->datatype != DLOCAL) {
+ offset_reg1 = used_virtual_registers[RegClass_GPR]++;
+ add_immediate_lo(offset_reg1, base_reg, obj, 0, 1);
+ obj = NULL;
+ }
+
+ if (offset != (short)offset) {
+ if (opcode == PC_LWZ && dest_reg == 12)
+ offset_reg2 = 12;
+ else if (opcode == PC_LWZ && dest_reg == 11)
+ offset_reg2 = 11;
+ else
+ offset_reg2 = used_virtual_registers[RegClass_GPR]++;
+
+ emitpcode(PC_ADDIS, offset_reg2, offset_reg1, 0, (short) ((offset >> 16) + ((offset & 0x8000) >> 15)));
+ offset = (short) offset;
+ offset_reg1 = offset_reg2;
+ }
+
+ if (opcode == PC_STVX || opcode == PC_LVX) {
+ offset_reg2 = 0;
+ if (obj) {
+ addi_tmp = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADDI, addi_tmp, offset_reg1, obj, offset);
+ offset_reg1 = addi_tmp;
+ } else if (offset) {
+ offset_reg2 = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LI, offset_reg2, offset);
+ }
+ if (!offset_reg2)
+ emitpcode(opcode, dest_reg, 0, offset_reg1);
+ else
+ emitpcode(opcode, dest_reg, offset_reg1, offset_reg2);
+ } else {
+ emitpcode(opcode, dest_reg, offset_reg1, obj, offset);
+ }
+}