diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
commit | 094b96ca1df4a035b5f93c351f773306c0241f3f (patch) | |
tree | 95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/unsorted/Operands.c | |
parent | fc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff) | |
download | MWCC-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/unsorted/Operands.c')
-rw-r--r-- | compiler_and_linker/unsorted/Operands.c | 1040 |
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); - } -} |