summaryrefslogtreecommitdiff
path: root/compiler_and_linker/unsorted/Operands.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/unsorted/Operands.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.tar.gz
MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.zip
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/unsorted/Operands.c')
-rw-r--r--compiler_and_linker/unsorted/Operands.c1040
1 files changed, 0 insertions, 1040 deletions
diff --git a/compiler_and_linker/unsorted/Operands.c b/compiler_and_linker/unsorted/Operands.c
deleted file mode 100644
index c5da285..0000000
--- a/compiler_and_linker/unsorted/Operands.c
+++ /dev/null
@@ -1,1040 +0,0 @@
-#include "compiler/Operands.h"
-#include "compiler/CError.h"
-#include "compiler/CMachine.h"
-#include "compiler/CParser.h"
-#include "compiler/CodeGen.h"
-#include "compiler/CompilerTools.h"
-#include "compiler/PCode.h"
-#include "compiler/PCodeInfo.h"
-#include "compiler/PCodeUtilities.h"
-#include "compiler/RegisterInfo.h"
-#include "compiler/Registers.h"
-#include "compiler/StackFrame.h"
-#include "compiler/TOC.h"
-#include "compiler/enode.h"
-#include "compiler/objects.h"
-
-unsigned long long uns_to_float_cc = 0x4330000000000000;
-unsigned long long int_to_float_cc = 0x4330000080000000;
-Float one_point_zero = {1.0};
-
-void load_immediate(short reg, SInt32 value) {
- short tmpreg = reg;
- short tmpreg2;
-
- if (!FITS_IN_SHORT(value)) {
- if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(value))
- tmpreg = used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_LIS, tmpreg2 = tmpreg, 0, (short) HIGH_PART(value));
- if (LOW_PART_BUGGY(value))
- emitpcode(PC_ADDI, reg, tmpreg2, 0, LOW_PART(value));
- } else {
- emitpcode(PC_LI, reg, value);
- }
-}
-
-static void set_op_flags(Operand *op, ENode *expr) {
- CError_ASSERT(118, op);
-
- if (expr) {
- if (expr->type == EINTCONST) {
- op->flags = 0;
- if (expr->flags & ENODE_FLAG_VOLATILE)
- op->flags |= OpndFlags_Volatile;
- if (expr->flags & ENODE_FLAG_CONST)
- op->flags |= OpndFlags_Const;
- } else {
- op->flags = CParserIsVolatileExpr(expr) ? OpndFlags_Volatile : 0;
- op->flags |= CParserIsConstExpr(expr) ? OpndFlags_Const : 0;
- }
- } else {
- op->flags = 0;
- }
-}
-
-void symbol_operand(Operand *op, Object *obj) {
- memclrw(op, sizeof(Operand));
- op->optype = OpndType_Symbol;
- op->object = obj;
-}
-
-void indirect(Operand *op, ENode *expr) {
- switch (op->optype) {
- case OpndType_GPRPair:
- CError_FATAL(163);
- case OpndType_CRField:
- case OpndType_IndirectGPR_ImmOffset:
- case OpndType_IndirectGPR_Indexed:
- case OpndType_IndirectSymbol:
- if (op->optype)
- Coerce_to_register(op, TYPE(&void_ptr), 0);
- case OpndType_GPR:
- op->immOffset = 0;
- op->object = NULL;
- case OpndType_GPR_ImmOffset:
- op->optype = OpndType_IndirectGPR_ImmOffset;
- set_op_flags(op, expr);
- break;
- case OpndType_GPR_Indexed:
- op->optype = OpndType_IndirectGPR_Indexed;
- set_op_flags(op, expr);
- break;
- case OpndType_Absolute:
- if (FITS_IN_SHORT(op->immediate)) {
- op->reg = 0;
- op->immOffset = op->immediate;
- } else {
- emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(op->immediate));
- op->immOffset = LOW_PART(op->immediate);
- }
- op->object = NULL;
- op->optype = OpndType_IndirectGPR_ImmOffset;
- set_op_flags(op, expr);
- break;
- case OpndType_Symbol:
- op->optype = OpndType_IndirectSymbol;
- set_op_flags(op, expr);
- break;
- default:
- CError_FATAL(215);
- }
-}
-
-#define COMBO_OP(a, b) (b + (a * 11))
-
-void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut) {
- Operand *tmp_op;
- int tmp;
-
- if (opA->optype == OpndType_Symbol || opA->optype == OpndType_IndirectSymbol)
- coerce_to_addressable(opA);
- if (opB->optype == OpndType_Symbol || opB->optype == OpndType_IndirectSymbol)
- coerce_to_addressable(opB);
-
- switch (COMBO_OP(opA->optype, opB->optype)) {
- case COMBO_OP(OpndType_GPR, OpndType_GPR):
- opOut->optype = OpndType_GPR_Indexed;
- opOut->reg = opA->reg;
- opOut->regOffset = opB->reg;
- break;
- case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_ImmOffset):
- if (FITS_IN_SHORT(opA->immOffset + opB->immOffset) && (!opA->object || !opB->object)) {
- opB->immOffset += opA->immOffset;
- if (!opB->object)
- opB->object = opA->object;
- } else {
- tmp = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
- add_immediate(tmp, opA->reg, opA->object, opA->immOffset);
- opA->reg = tmp;
- }
- case COMBO_OP(OpndType_GPR, OpndType_GPR_ImmOffset):
- tmp_op = opA;
- opA = opB;
- opB = tmp_op;
- case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR):
- if (opA->reg == _FP_ || opA->reg == _CALLER_SP_) {
- opOut->optype = OpndType_GPR_Indexed;
- opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
- opOut->regOffset = opB->reg;
- add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset));
- } else if (opB->reg == _FP_ || opB->reg == _CALLER_SP_) {
- opOut->optype = OpndType_GPR_Indexed;
- opOut->reg = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
- opOut->regOffset = opA->reg;
- add_immediate(opOut->reg, opB->reg, opA->object, LOW_PART(opA->immOffset));
- } else if (opA->object) {
- opOut->optype = OpndType_GPR_Indexed;
- opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
- opOut->regOffset = opB->reg;
- add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset));
- } else {
- opOut->optype = OpndType_GPR_ImmOffset;
- opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- opOut->immOffset = opA->immOffset;
- opOut->object = opA->object;
- emitpcode(PC_ADD, opOut->reg, opA->reg, opB->reg);
- }
- break;
- case COMBO_OP(OpndType_GPR, OpndType_GPR_Indexed):
- tmp_op = opA;
- opA = opB;
- opB = tmp_op;
- case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR):
- opOut->optype = OpndType_GPR_Indexed;
- opOut->reg = opA->reg;
- opOut->regOffset = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_ADD, opOut->regOffset, opA->regOffset, opB->reg);
- break;
- case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_Indexed):
- tmp_op = opA;
- opA = opB;
- opB = tmp_op;
- case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_ImmOffset):
- if (opB->object) {
- opOut->optype = OpndType_GPR_Indexed;
- opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg
- : used_virtual_registers[RegClass_GPR]++;
- opOut->regOffset = used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset);
- add_immediate(opOut->regOffset, opB->reg, opB->object, opB->immOffset);
- } else {
- opOut->optype = OpndType_GPR_ImmOffset;
- opOut->immOffset = opB->immOffset;
- opOut->object = opB->object;
- opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg
- : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset);
- emitpcode(PC_ADD, opOut->reg, opOut->reg, opB->reg);
- }
- break;
- case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_Indexed):
- opOut->optype = OpndType_GPR_Indexed;
- opOut->reg = opA->reg;
- opOut->regOffset = (output_reg && (output_reg != opA->regOffset)) ? output_reg
- : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_ADD, opOut->regOffset, opB->reg, opB->regOffset);
- emitpcode(PC_ADD, opOut->regOffset, opOut->regOffset, opA->regOffset);
- break;
- case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_Absolute):
- tmp_op = opA;
- opA = opB;
- opB = tmp_op;
- case COMBO_OP(OpndType_Absolute, OpndType_GPR_ImmOffset):
- if (!opB->object) {
- opOut->optype = OpndType_GPR_ImmOffset;
- opOut->reg = opB->reg;
- opOut->immOffset = opB->immOffset;
- opOut->object = opB->object;
- if (FITS_IN_SHORT(opOut->immOffset + opA->immediate)) {
- opOut->immOffset += opA->immediate;
- } else {
- opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- if (!HIGH_PART(opA->immediate)) {
- emitpcode(PC_ADDI, opOut->reg, opB->reg, 0, LOW_PART(opA->immediate));
- } else {
- emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->immediate));
- if (FITS_IN_SHORT(opOut->immOffset + LOW_PART(opA->immediate))) {
- opOut->immOffset += LOW_PART(opA->immediate);
- } else {
- emitpcode(PC_ADDI, opOut->reg, opOut->reg, 0, LOW_PART(opA->immediate));
- }
- }
- }
- break;
- } else if (opB->object->datatype == DLOCAL && can_add_displ_to_local(opB->object, opB->immOffset + opA->immediate)) {
- opOut->optype = OpndType_GPR_ImmOffset;
- opOut->object = opB->object;
- opOut->reg = opB->reg;
- opOut->immOffset = LOW_PART(opB->immOffset + opA->immediate);
- break;
- } else {
- opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- add_immediate(opOut->reg, opB->reg, opB->object, opB->immOffset);
- opB->optype = OpndType_GPR;
- opB->reg = opOut->reg;
- tmp_op = opA;
- opA = opB;
- opB = tmp_op;
- }
- case COMBO_OP(OpndType_GPR, OpndType_Absolute):
- tmp_op = opA;
- opA = opB;
- opB = tmp_op;
- case COMBO_OP(OpndType_Absolute, OpndType_GPR):
- opOut->optype = (opA->immediate != 0) ? OpndType_GPR_ImmOffset : OpndType_GPR;
- opOut->immOffset = LOW_PART(opA->immediate);
- opOut->object = NULL;
- if (FITS_IN_SHORT(opA->immediate)) {
- opOut->reg = opB->reg;
- } else {
- opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->immediate));
- }
- break;
- case COMBO_OP(OpndType_GPR_Indexed, OpndType_Absolute):
- tmp_op = opA;
- opA = opB;
- opB = tmp_op;
- case COMBO_OP(OpndType_Absolute, OpndType_GPR_Indexed):
- opOut->optype = OpndType_GPR_Indexed;
- opOut->reg = opB->reg;
- opOut->regOffset = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
- if (!HIGH_PART(opA->immediate)) {
- emitpcode(PC_ADDI, opOut->regOffset, opB->regOffset, 0, LOW_PART(opA->immediate));
- } else {
- emitpcode(PC_ADDIS, opOut->regOffset, opB->regOffset, 0, (short) HIGH_PART(opA->immediate));
- if (LOW_PART_BUGGY(opA->immediate))
- emitpcode(PC_ADDI, opOut->regOffset, opOut->regOffset, 0, LOW_PART(opA->immediate));
- }
- break;
- case COMBO_OP(OpndType_Absolute, OpndType_Absolute):
- opOut->optype = OpndType_Absolute;
- opOut->immediate = opA->immediate + opB->immediate;
- break;
- default:
- CError_FATAL(415);
- }
-}
-
-void coerce_to_addressable(Operand *op) {
- UInt32 offset;
- short reg;
- short flag;
- short tmp;
- Object *obj;
-
- flag = 0;
- obj = op->object;
- tmp = 0;
-
- switch (op->optype) {
- case OpndType_GPR:
- case OpndType_GPR_ImmOffset:
- case OpndType_GPR_Indexed:
- case OpndType_GPRPair:
- case OpndType_Absolute:
- case OpndType_VR:
- case OpndType_CRField:
- case OpndType_IndirectGPR_ImmOffset:
- case OpndType_IndirectGPR_Indexed:
- break;
- case OpndType_IndirectSymbol:
- flag = 1;
- case OpndType_Symbol:
- if (obj->datatype == DLOCAL) {
- if (!local_is_16bit_offset(obj)) {
- reg = used_virtual_registers[RegClass_GPR]++;
- op_absolute_ha(reg, local_base_register(obj), obj, 0, 1);
- op->optype = OpndType_GPR_ImmOffset;
- op->reg = reg;
- op->object = obj;
- } else {
- op->optype = OpndType_GPR_ImmOffset;
- op->reg = local_base_register(obj);
- op->object = obj;
- }
- } else if (obj->datatype == DABSOLUTE) {
- offset = obj->u.address;
- if (FITS_IN_SHORT(offset)) {
- op->reg = 0;
- op->immOffset = obj->u.address;
- } else {
- emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(offset));
- op->immOffset = LOW_PART(obj->u.address);
- }
- op->object = obj;
- op->optype = OpndType_GPR_ImmOffset;
- } else {
- if (copts.codegen_pic)
- tmp = pic_base_reg;
- reg = used_virtual_registers[RegClass_GPR]++;
- op_absolute_ha(reg, tmp, obj, 0, 1);
- op->optype = OpndType_GPR_ImmOffset;
- op->reg = reg;
- }
- if (flag) {
- if (op->optype == OpndType_GPR_ImmOffset) {
- op->optype = OpndType_IndirectGPR_ImmOffset;
- } else {
- CError_FATAL(563);
- }
- }
- break;
- default:
- CError_FATAL(581);
- }
-}
-
-void Coerce_to_register(Operand *op, Type *type, short output_reg) {
- SInt32 offset;
- Opcode opcode;
- short reg;
- short tmp;
- short cond_neg;
- short cond;
- short bit_offset;
- short bit_size;
-
- if (TYPE_IS_8BYTES(type)) {
- coerce_to_register_pair(op, type, output_reg, 0);
- return;
- }
-
- coerce_to_addressable(op);
- switch (op->optype) {
- case OpndType_GPRPair:
- return;
- case OpndType_GPR:
- return;
- case OpndType_GPR_ImmOffset:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- add_immediate(reg, op->reg, op->object, op->immOffset);
- break;
- case OpndType_GPR_Indexed:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_ADD, reg, op->reg, op->regOffset);
- break;
- case OpndType_Absolute:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- offset = op->immediate;
- if (FITS_IN_SHORT(offset)) {
- emitpcode(PC_LI, reg, offset);
- } else {
- tmp = reg;
- if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(offset))
- tmp = used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_LIS, tmp, 0, (short) HIGH_PART(offset));
- if (LOW_PART_BUGGY(offset))
- emitpcode(PC_ADDI, reg, tmp, 0, LOW_PART(offset));
- }
- break;
- case OpndType_IndirectGPR_ImmOffset:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- opcode = PC_LWZ;
- if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
- switch (type->size) {
- case 1:
- opcode = PC_LBZ;
- break;
- case 2:
- if (is_unsigned(type))
- opcode = PC_LHZ;
- else
- opcode = PC_LHA;
- break;
- }
- } else {
- CError_ASSERT(680, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
- }
- load_store_register(opcode, reg, op->reg, op->object, op->immOffset);
- setpcodeflags(op->flags);
- break;
- case OpndType_IndirectGPR_Indexed:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- opcode = PC_LWZX;
- if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
- switch (type->size) {
- case 1:
- opcode = PC_LBZX;
- break;
- case 2:
- if (is_unsigned(type))
- opcode = PC_LHZX;
- else
- opcode = PC_LHAX;
- break;
- }
- } else {
- CError_ASSERT(724, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
- }
- emitpcode(opcode, reg, op->reg, op->regOffset);
- setpcodeflags(op->flags);
- break;
- case OpndType_CRField:
- cond_neg = 0;
- cond = 0;
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_MFCR, tmp = reg);
- switch (op->regOffset) {
- case ENOTEQU:
- cond_neg = 1;
- case EEQU:
- cond = 2;
- break;
- case EGREATEREQU:
- cond_neg = 1;
- case ELESS:
- cond = 0;
- break;
- case ELESSEQU:
- cond_neg = 1;
- case EGREATER:
- cond = 1;
- break;
- default:
- CError_FATAL(758);
- }
- bit_offset = cond + (op->reg << 2);
- bit_size = 1;
- emitpcode(PC_RLWINM, tmp, tmp, (bit_size + bit_offset) & 31, 32 - bit_size, 31);
- if (cond_neg)
- emitpcode(PC_XORI, tmp, tmp, 1);
- break;
- default:
- CError_FATAL(769);
- }
-
- op->optype = OpndType_GPR;
- op->reg = reg;
-}
-
-void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short output_regHi) {
- SInt32 offset;
- short reg;
- short regHi;
- short tmp1;
- short tmp2;
-
- regHi = -1;
-
- CError_ASSERT(794, TYPE_IS_8BYTES(type) || (IS_TYPE_STRUCT(type) && type->size == 8));
-
- coerce_to_addressable(op);
- switch (op->optype) {
- case OpndType_GPRPair:
- if (output_reg && !output_regHi)
- output_regHi = used_virtual_registers[RegClass_GPR]++;
- if (output_regHi && !output_reg)
- output_reg = used_virtual_registers[RegClass_GPR]++;
- if (op->reg != output_reg || op->regHi != output_regHi) {
- tmp1 = output_reg ? output_reg : op->reg;
- tmp2 = output_regHi ? output_regHi : op->regHi;
- if (tmp1 != op->reg) {
- if (tmp1 == op->regHi) {
- CError_ASSERT(818, tmp1 != tmp2);
- emitpcode(PC_MR, tmp2, op->regHi);
- emitpcode(PC_MR, tmp1, op->reg);
- } else {
- emitpcode(PC_MR, tmp1, op->reg);
- if (op->regHi != tmp2)
- emitpcode(PC_MR, tmp2, op->regHi);
- }
- } else if (tmp2 != op->regHi) {
- if (tmp2 == op->reg) {
- CError_ASSERT(832, tmp1 != tmp2);
- emitpcode(PC_MR, tmp1, op->reg);
- emitpcode(PC_MR, tmp2, op->regHi);
- } else {
- emitpcode(PC_MR, tmp2, op->regHi);
- if (op->reg != tmp1)
- emitpcode(PC_MR, tmp1, op->reg);
- }
- }
- }
- reg = op->reg;
- regHi = op->regHi;
- break;
- case OpndType_GPR:
- CError_FATAL(849);
- break;
- case OpndType_GPR_ImmOffset:
- CError_FATAL(852);
- break;
- case OpndType_GPR_Indexed:
- CError_FATAL(855);
- break;
- case OpndType_Absolute:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- offset = op->immediate;
- if (FITS_IN_SHORT(offset)) {
- emitpcode(PC_LI, reg, offset);
- } else {
- tmp1 = reg;
- if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(offset))
- tmp1 = used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_LIS, tmp1, 0, (short) HIGH_PART(offset));
- if (LOW_PART_BUGGY(offset))
- emitpcode(PC_ADDI, reg, tmp1, 0, LOW_PART(offset));
- }
- regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
- if (is_unsigned(type) || offset >= 0)
- load_immediate(regHi, 0);
- else
- load_immediate(regHi, -1);
- break;
- case OpndType_IndirectGPR_ImmOffset:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
- if (op->reg == regHi) {
- if (op->reg == reg) {
- CError_FATAL(887);
- } else {
- load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset);
- setpcodeflags(op->flags);
- load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset);
- setpcodeflags(op->flags);
- }
- } else {
- load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset);
- setpcodeflags(op->flags);
- load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset);
- setpcodeflags(op->flags);
- }
- break;
- case OpndType_IndirectGPR_Indexed:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_ADD, reg, op->reg, op->regOffset);
- load_store_register(PC_LWZ, regHi, reg, NULL, high_offset);
- setpcodeflags(op->flags);
- load_store_register(PC_LWZ, reg, reg, NULL, low_offset);
- setpcodeflags(op->flags);
- break;
- default:
- CError_FATAL(912);
- }
-
- if (regHi == -1) {
- CError_FATAL(916);
- } else {
- op->optype = OpndType_GPRPair;
- op->reg = reg;
- op->regHi = regHi;
- }
-}
-
-void Coerce_to_fp_register(Operand *op, Type *type, short output_reg) {
- short reg;
-
- coerce_to_addressable(op);
-
- switch (op->optype) {
- case OpndType_FPR:
- reg = op->reg;
- break;
- case OpndType_IndirectGPR_ImmOffset:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
- load_store_register((type->size == 4) ? PC_LFS : PC_LFD, reg, op->reg, op->object, op->immOffset);
- setpcodeflags(op->flags);
- break;
- case OpndType_IndirectGPR_Indexed:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
- emitpcode((type->size == 4) ? PC_LFSX : PC_LFDX, reg, op->reg, op->regOffset, 0, 0x390);
- setpcodeflags(op->flags);
- break;
- default:
- CError_FATAL(986);
- }
-
- op->optype = OpndType_FPR;
- op->reg = reg;
-}
-
-void Coerce_to_v_register(Operand *op, Type *type, short output_reg) {
- short reg;
-
- coerce_to_addressable(op);
-
- switch (op->optype) {
- case OpndType_VR:
- reg = op->reg;
- break;
- case OpndType_IndirectGPR_ImmOffset:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++;
- load_store_register(PC_LVX, reg, op->reg, op->object, op->immOffset);
- setpcodeflags(op->flags);
- break;
- case OpndType_IndirectGPR_Indexed:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++;
- emitpcode(PC_LVX, reg, op->reg, op->regOffset);
- setpcodeflags(op->flags);
- break;
- case OpndType_Absolute:
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++;
- switch (TYPE_STRUCT(type)->stype) {
- case STRUCT_VECTOR_UCHAR:
- case STRUCT_VECTOR_SCHAR:
- case STRUCT_VECTOR_BCHAR:
- emitpcode(PC_VSPLTISB, reg, op->immediate);
- break;
- case STRUCT_VECTOR_USHORT:
- case STRUCT_VECTOR_SSHORT:
- case STRUCT_VECTOR_BSHORT:
- case STRUCT_VECTOR_PIXEL:
- emitpcode(PC_VSPLTISH, reg, op->immediate);
- break;
- case STRUCT_VECTOR_UINT:
- case STRUCT_VECTOR_SINT:
- case STRUCT_VECTOR_BINT:
- case STRUCT_VECTOR_FLOAT:
- emitpcode(PC_VSPLTISW, reg, op->immediate);
- break;
- default:
- CError_FATAL(1049);
- }
- op->optype = OpndType_VR;
- op->reg = reg;
- setpcodeflags(op->flags);
- break;
- default:
- CError_FATAL(1059);
- }
-
- op->optype = OpndType_VR;
- op->reg = reg;
-}
-
-void store(short reg, Operand *op, Type *type) {
- Opcode opcode;
-
- coerce_to_addressable(op);
- switch (op->optype) {
- case OpndType_IndirectGPR_ImmOffset:
- opcode = PC_STW;
- if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
- switch (type->size) {
- case 1:
- opcode = PC_STB;
- break;
- case 2:
- opcode = PC_STH;
- break;
- }
- } else {
- CError_ASSERT(1171, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
- }
- load_store_register(opcode, reg, op->reg, op->object, op->immOffset);
- setpcodeflags(op->flags);
- break;
- case OpndType_IndirectGPR_Indexed:
- opcode = PC_STWX;
- if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
- switch (type->size) {
- case 1:
- opcode = PC_STBX;
- break;
- case 2:
- opcode = PC_STHX;
- break;
- }
- } else {
- CError_ASSERT(1188, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
- }
- emitpcode(opcode, reg, op->reg, op->regOffset);
- setpcodeflags(op->flags);
- break;
- default:
- CError_FATAL(1193);
- }
-}
-
-void store_pair(short reg, short regHi, Operand *op, Type *type) {
- short tmp;
-
- CError_ASSERT(1208, TYPE_IS_8BYTES(type));
-
- coerce_to_addressable(op);
- switch (op->optype) {
- case OpndType_IndirectGPR_ImmOffset:
- load_store_register(PC_STW, reg, op->reg, op->object, op->immOffset + low_offset);
- setpcodeflags(op->flags);
- load_store_register(PC_STW, regHi, op->reg, op->object, op->immOffset + high_offset);
- setpcodeflags(op->flags);
- break;
- case OpndType_IndirectGPR_Indexed:
- tmp = used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_ADD, tmp, op->reg, op->regOffset);
- load_store_register(PC_STW, reg, tmp, NULL, low_offset);
- setpcodeflags(op->flags);
- load_store_register(PC_STW, regHi, tmp, NULL, high_offset);
- setpcodeflags(op->flags);
- break;
- default:
- CError_FATAL(1228);
- }
-}
-
-void store_fp(short reg, Operand *op, Type *type) {
- coerce_to_addressable(op);
- switch (op->optype) {
- case OpndType_IndirectGPR_ImmOffset:
- load_store_register((type->size == 4) ? PC_STFS : PC_STFD, reg, op->reg, op->object, op->immOffset);
- setpcodeflags(op->flags);
- break;
- case OpndType_IndirectGPR_Indexed:
- emitpcode((type->size == 4) ? PC_STFSX : PC_STFDX, reg, op->reg, op->regOffset);
- setpcodeflags(op->flags);
- break;
- default:
- CError_FATAL(1259);
- }
-}
-
-void store_v(short reg, Operand *op, Type *tstruct) {
- coerce_to_addressable(op);
- switch (op->optype) {
- case OpndType_IndirectGPR_ImmOffset:
- load_store_register(PC_STVX, reg, op->reg, op->object, op->immOffset);
- setpcodeflags(op->flags);
- break;
- case OpndType_IndirectGPR_Indexed:
- emitpcode(PC_STVX, reg, op->reg, op->regOffset);
- setpcodeflags(op->flags);
- break;
- default:
- CError_FATAL(1283);
- }
-}
-
-static Boolean last_matches_rlwinm_or_exts(Operand *op, short opcode, short b, short c) {
- PCode *pc;
-
- if (pclastblock->pcodeCount <= 0)
- return 0;
-
- pc = pclastblock->lastPCode;
- if (pc->args[0].kind != PCOp_REGISTER || pc->args[0].arg != RegClass_GPR || pc->args[0].data.reg.reg != op->reg)
- return 0;
-
- if (pc->op != opcode && (opcode != PC_EXTSH || pc->op != PC_EXTSB))
- return 0;
-
- if (opcode == PC_RLWINM) {
- if (pc->args[2].data.imm.value != 0 || pc->args[3].data.imm.value != b || pc->args[4].data.imm.value != c)
- return 0;
- }
-
- return 1;
-}
-
-void extend32(Operand *op, Type *type, short output_reg) {
- int r28;
- int reg;
-
- r28 = op->optype >= OpndType_IndirectGPR_ImmOffset;
- if (op->optype != OpndType_GPR)
- Coerce_to_register(op, type, output_reg);
-
- switch (type->size) {
- case 1:
- if (is_unsigned(type)) {
- if (r28)
- return;
- if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 24, 31))
- return;
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_RLWINM, reg, op->reg, 0, 24, 31);
- } else {
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- if (last_matches_rlwinm_or_exts(op, PC_EXTSB, 0, 0))
- return;
- emitpcode(PC_EXTSB, reg, op->reg);
- }
- break;
- case 2:
- if (r28)
- return;
- if (is_unsigned(type)) {
- if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 16, 31))
- return;
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_RLWINM, reg, op->reg, 0, 16, 31);
- } else {
- if (last_matches_rlwinm_or_exts(op, PC_EXTSH, 0, 0))
- return;
- reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_EXTSH, reg, op->reg);
- }
- break;
- default:
- CError_FATAL(1389);
- }
-
- op->optype = OpndType_GPR;
- op->reg = reg;
-}
-
-void extend64(Operand *op, Type *type, short output_reg, short output_regHi) {
- short tmp;
- short regHi;
-
- if (op->optype != OpndType_GPR)
- Coerce_to_register(op, type, output_reg);
-
- regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
- if (regHi == op->reg) {
- tmp = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_MR, tmp, op->reg);
- op->reg = tmp;
- }
-
- if (is_unsigned(type))
- load_immediate(regHi, 0);
- else
- emitpcode(PC_SRAWI, regHi, op->reg, 31);
-
- op->optype = OpndType_GPRPair;
- op->regHi = regHi;
-}
-
-void load_floating_constant(short reg, Type *type, Float *data) {
- Object *object;
- Object *indObject;
- Operand op1;
- Operand op2;
- Operand op3;
- SInt32 offset = 0;
-
- memclrw(&op1, sizeof(Operand));
-
- object = CreateFloatConst(type, data, &offset);
- indObject = createIndirect(object, 0, 1);
-
- if (indObject) {
- symbol_operand(&op1, indObject);
- indirect(&op1, NULL);
- } else {
- symbol_operand(&op1, object);
- }
-
- if (offset) {
- op2 = op1;
- memclrw(&op3, sizeof(Operand));
- op3.optype = OpndType_Absolute;
- op3.immediate = offset;
- if (op2.optype != OpndType_GPR)
- Coerce_to_register(&op2, TYPE(&void_ptr), 0);
- combine(&op2, &op3, 0, &op1);
- }
-
- indirect(&op1, NULL);
- if (op1.optype != OpndType_FPR)
- Coerce_to_fp_register(&op1, type, reg);
-}
-
-void convert_integer_to_floating(Operand *op, Boolean is_single, short output_reg) {
- Operand temp_op;
- Float d;
- int const_reg;
- int tmp_reg;
- int work_reg;
- int result_reg;
- Opcode opcode;
-
- symbol_operand(&temp_op, maketemporary(TYPE(&stdouble)));
- coerce_to_addressable(&temp_op);
- d.value = *((double *) &int_to_float_cc);
-
- const_reg = used_virtual_registers[RegClass_FPR]++;
- load_floating_constant(const_reg, TYPE(&stdouble), &d);
-
- tmp_reg = used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_XORIS, tmp_reg, op->reg, 0x8000);
- load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, low_offset);
-
- emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330);
- load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset);
-
- load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0);
-
- result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
- if (is_single != 0)
- opcode = PC_FSUBS;
- else
- opcode = PC_FSUB;
- emitpcode(opcode, result_reg, work_reg, const_reg);
-
- op->optype = OpndType_FPR;
- op->reg = result_reg;
-}
-
-void convert_unsigned_to_floating(Operand *op, Boolean is_single, short output_reg) {
- Operand temp_op;
- Float d;
- int const_reg;
- int tmp_reg;
- int work_reg;
- int result_reg;
- Opcode opcode;
-
- symbol_operand(&temp_op, maketemporary(TYPE(&stdouble)));
- coerce_to_addressable(&temp_op);
- d.value = *((double *) &uns_to_float_cc);
-
- const_reg = used_virtual_registers[RegClass_FPR]++;
- load_floating_constant(const_reg, TYPE(&stdouble), &d);
-
- load_store_register(PC_STW, op->reg, temp_op.reg, temp_op.object, low_offset);
-
- emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330);
- load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset);
-
- load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0);
-
- result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
- if (is_single != 0)
- opcode = PC_FSUBS;
- else
- opcode = PC_FSUB;
- emitpcode(opcode, result_reg, work_reg, const_reg);
-
- op->optype = OpndType_FPR;
- op->reg = result_reg;
-}
-
-void convert_floating_to_integer(Operand *op, short output_reg) {
- Operand temp_op;
- int tmp_reg;
- int result_reg;
-
- symbol_operand(&temp_op, maketemporary(TYPE(&stdouble)));
- coerce_to_addressable(&temp_op);
-
- tmp_reg = used_virtual_registers[RegClass_FPR]++;
- emitpcode(PC_FCTIWZ, tmp_reg, op->reg);
- load_store_register(PC_STFD, tmp_reg, temp_op.reg, temp_op.object, 0);
-
- result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- load_store_register(PC_LWZ, result_reg, temp_op.reg, temp_op.object, low_offset);
-
- op->optype = OpndType_GPR;
- op->reg = result_reg;
-}
-
-void convert_floating_to_unsigned(Operand *op, short output_reg) {
- static UInt32 used_regs[RegClassMax] = {0, 0, 0, 2, 0};
-
- if (op->reg != 1)
- emitpcode(PC_FMR, 1, op->reg);
-
- branch_subroutine(rt_cvt_fp2unsigned, 0, used_regs);
-
- op->optype = OpndType_GPR;
- op->reg = used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_MR, op->reg, 3);
-}
-
-void extract_bitfield(Operand *input_op, TypeBitfield *tbitfield, short output_reg, Operand *output_op) {
- int r27;
- int offset;
- int tmp_reg;
- int output;
-
- offset = tbitfield->bitlength;
- output = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- r27 = tbitfield->offset + (32 - (tbitfield->bitfieldtype->size * 8));
- if (is_unsigned(tbitfield->bitfieldtype)) {
- emitpcode(PC_RLWINM, output, input_op->reg, (r27 + offset) & 31, 32 - offset, 31);
- } else if (r27 == 0) {
- emitpcode(PC_SRAWI, output, input_op->reg, 32 - offset);
- } else {
- tmp_reg = used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_RLWINM, tmp_reg, input_op->reg, r27 & 31, 0, offset);
- emitpcode(PC_SRAWI, output, tmp_reg, 32 - offset);
- }
-
- output_op->optype = OpndType_GPR;
- output_op->reg = output;
-}
-
-void insert_bitfield(short reg, Operand *op, TypeBitfield *tbitfield) {
- int offset = tbitfield->bitlength;
- int r7 = tbitfield->offset + (32 - (tbitfield->bitfieldtype->size * 8));
- emitpcode(PC_RLWIMI, op->reg, reg, 32 - (r7 + offset), r7, r7 + offset - 1);
-}
-
-void load_address(short dest_reg, Operand *op) {
- coerce_to_addressable(op);
- if (op->optype == OpndType_IndirectGPR_ImmOffset) {
- if (!op->immOffset && !op->object) {
- if (op->reg != dest_reg)
- emitpcode(PC_MR, dest_reg, op->reg);
- } else {
- add_immediate(dest_reg, op->reg, op->object, (SInt16) op->immOffset);
- }
- } else if (op->optype == OpndType_IndirectGPR_Indexed) {
- emitpcode(PC_ADD, dest_reg, op->reg, op->regOffset);
- } else {
- CError_FATAL(1849);
- }
-}