#include "compiler/StructMoves.h" #include "compiler/CError.h" #include "compiler/CParser.h" #include "compiler/CodeGen.h" #include "compiler/Operands.h" #include "compiler/PCode.h" #include "compiler/PCodeUtilities.h" #include "compiler/Registers.h" void make_addressable(Operand *opnd, SInt32 offset, int unusedArg) { int reg; if (opnd->optype == OpndType_IndirectSymbol) coerce_to_addressable(opnd); if (opnd->optype != OpndType_IndirectGPR_ImmOffset || (opnd->immOffset + offset) > 0x7FFF) { reg = used_virtual_registers[RegClass_GPR]++; load_address(reg, opnd); opnd->optype = OpndType_IndirectGPR_ImmOffset; opnd->reg = reg; opnd->object = NULL; opnd->immOffset = 0; } } static void load_displaced_address(Operand *opnd, SInt32 offset) { int reg; reg = used_virtual_registers[RegClass_GPR]++; if (opnd->optype == OpndType_IndirectSymbol) coerce_to_addressable(opnd); if (opnd->optype == OpndType_IndirectGPR_ImmOffset) { offset += opnd->immOffset; if (!FITS_IN_SHORT(offset)) { add_immediate(reg, opnd->reg, opnd->object, opnd->immOffset); emitpcode(PC_ADDI, reg, reg, 0, offset - opnd->immOffset); } else { add_immediate(reg, opnd->reg, opnd->object, offset); } } else if (opnd->optype == OpndType_IndirectGPR_Indexed) { emitpcode(PC_ADD, reg, opnd->reg, opnd->regOffset); emitpcode(PC_ADDI, reg, reg, 0, offset); } else { CError_FATAL(80); } opnd->optype = OpndType_IndirectGPR_ImmOffset; opnd->reg = reg; opnd->object = NULL; opnd->immOffset = 0; } static void move_block_via_load_store(Operand *dst, Operand *src, SInt32 len, SInt32 align) { SInt32 step; SInt32 pos; int floatReg; int reg; if (src->optype == OpndType_IndirectSymbol) coerce_to_addressable(src); if (dst->optype == OpndType_IndirectSymbol) coerce_to_addressable(dst); if (len == 8) { floatReg = used_virtual_registers[RegClass_FPR]++; if (src->optype == OpndType_IndirectGPR_ImmOffset) { load_store_register(PC_LFD, floatReg, src->reg, src->object, src->immOffset); setpcodeflags(src->flags); } else if (src->optype == OpndType_IndirectGPR_Indexed) { emitpcode(PC_LFDX, floatReg, src->reg, src->regOffset); setpcodeflags(src->flags); } else { CError_FATAL(145); } if (dst->optype == OpndType_IndirectGPR_ImmOffset) { load_store_register(PC_STFD, floatReg, dst->reg, dst->object, dst->immOffset); setpcodeflags(dst->flags); } else if (dst->optype == OpndType_IndirectGPR_Indexed) { emitpcode(PC_STFDX, floatReg, dst->reg, dst->regOffset); setpcodeflags(dst->flags); } else { CError_FATAL(157); } return; } if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; } else { step = ((UInt32) len > 4) ? 4 : ((UInt32) len <= 2) ? len : 2; } if (step != len) { if (dst->optype == OpndType_IndirectGPR_Indexed) make_addressable(dst, len, 0); if (src->optype == OpndType_IndirectGPR_Indexed) make_addressable(src, len, 0); } for (pos = 0; len != 0; len -= step, pos += step) { reg = used_virtual_registers[RegClass_GPR]++; if (src->optype == OpndType_IndirectGPR_ImmOffset) { load_store_register( (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, reg, src->reg, src->object, src->immOffset + pos ); setpcodeflags(src->flags); } else if (src->optype == OpndType_IndirectGPR_Indexed) { emitpcode( (step == 1) ? PC_LBZX : (step == 2) ? PC_LHZX : PC_LWZX, reg, src->reg, src->regOffset ); setpcodeflags(src->flags); } else { CError_FATAL(183); } if (dst->optype == OpndType_IndirectGPR_ImmOffset) { load_store_register( (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, reg, dst->reg, dst->object, dst->immOffset + pos ); setpcodeflags(dst->flags); } else if (dst->optype == OpndType_IndirectGPR_Indexed) { emitpcode( (step == 1) ? PC_STBX : (step == 2) ? PC_STHX : PC_STWX, reg, dst->reg, dst->regOffset ); setpcodeflags(dst->flags); } else { CError_FATAL(195); } } } static void move_block_via_load_store_sequence(Operand *dst, Operand *src, SInt32 len, SInt32 align) { SInt32 pos; int i; SInt32 step; pos = 0; make_addressable(dst, len, 0); make_addressable(src, len, 0); if ((align % 8) == 0) { while (len >= 16) { int reg1 = used_virtual_registers[RegClass_FPR]++; int reg2 = used_virtual_registers[RegClass_FPR]++; load_store_register(PC_LFD, reg1, src->reg, src->object, src->immOffset + pos); setpcodeflags(src->flags); load_store_register(PC_LFD, reg2, src->reg, src->object, src->immOffset + pos + 8); setpcodeflags(src->flags); load_store_register(PC_STFD, reg1, dst->reg, dst->object, dst->immOffset + pos); setpcodeflags(dst->flags); load_store_register(PC_STFD, reg2, dst->reg, dst->object, dst->immOffset + pos + 8); setpcodeflags(dst->flags); pos += 16; len -= 16; } } while (len >= 8) { if ((align % 8) == 0) { int reg = used_virtual_registers[RegClass_FPR]++; load_store_register(PC_LFD, reg, src->reg, src->object, src->immOffset + pos); setpcodeflags(src->flags); load_store_register(PC_STFD, reg, dst->reg, dst->object, dst->immOffset + pos); setpcodeflags(dst->flags); pos += 8; len -= 8; } else { if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp > 2) ? 2 : 1; } else { step = 4; } for (i = 0; i < 8; i += (step * 2)) { int reg1 = used_virtual_registers[RegClass_GPR]++; int reg2 = used_virtual_registers[RegClass_GPR]++; load_store_register( (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, reg1, src->reg, src->object, src->immOffset + pos ); setpcodeflags(src->flags); load_store_register( (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, reg2, src->reg, src->object, src->immOffset + pos + step ); setpcodeflags(src->flags); load_store_register( (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, reg1, dst->reg, dst->object, dst->immOffset + pos ); setpcodeflags(dst->flags); load_store_register( (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, reg2, dst->reg, dst->object, dst->immOffset + pos + step ); setpcodeflags(dst->flags); pos += (step * 2); len -= (step * 2); } } } while (len) { int reg; if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; } else { step = ((UInt32) len > 4) ? 4 : ((UInt32) len <= 2) ? len : 2; } reg = used_virtual_registers[RegClass_GPR]++; load_store_register( (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, reg, src->reg, src->object, src->immOffset + pos ); setpcodeflags(src->flags); load_store_register( (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, reg, dst->reg, dst->object, dst->immOffset + pos ); setpcodeflags(dst->flags); len -= step; pos += step; } } static void move_block_via_inline_loop(Operand *dst, Operand *src, SInt32 len, SInt32 align) { PCodeLabel *label; // r25 SInt32 pos; // r25 SInt32 step; // r24 int reg1; // r22 int reg2; // r23 SInt32 remainder; // r23 label = makepclabel(); if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; } else { step = 4; } load_displaced_address(dst, -step); load_displaced_address(src, -step); CError_ASSERT(377, (len / step) != 0); reg1 = used_virtual_registers[RegClass_GPR]++; load_immediate(reg1, len / (step * 2)); emitpcode(PC_MTCTR, reg1); branch_label(label); reg1 = used_virtual_registers[RegClass_GPR]++; reg2 = used_virtual_registers[RegClass_GPR]++; load_store_register( (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, reg1, src->reg, NULL, step ); setpcodeflags(src->flags); load_store_register( (step == 1) ? PC_LBZU : (step == 2) ? PC_LHZU : PC_LWZU, reg2, src->reg, NULL, step * 2 ); setpcodeflags(src->flags); load_store_register( (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, reg1, dst->reg, NULL, step ); setpcodeflags(dst->flags); load_store_register( (step == 1) ? PC_STBU : (step == 2) ? PC_STHU : PC_STWU, reg2, dst->reg, NULL, step * 2 ); setpcodeflags(dst->flags); branch_decrement_always(PC_BDNZ, label); for (remainder = len & 7, pos = step; remainder != 0; remainder -= step, pos += step) { int reg; if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { SInt32 tmp = (align == 0) ? 1 : (align > remainder) ? remainder : align; step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; } else { step = ((UInt32) remainder > 4) ? 4 : ((UInt32) remainder <= 2) ? remainder : 2; } reg = used_virtual_registers[RegClass_GPR]++; load_store_register( (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, reg, src->reg, NULL, pos ); setpcodeflags(src->flags); load_store_register( (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, reg, dst->reg, NULL, pos ); setpcodeflags(dst->flags); } } void move_block(Operand *dst, Operand *src, SInt32 len, SInt32 align) { Operand myDst; myDst = *dst; CError_ASSERT(447, myDst.optype >= OpndType_IndirectGPR_ImmOffset); CError_ASSERT(449, src->optype >= OpndType_IndirectGPR_ImmOffset); if (len == 1 || len == 2 || len == 4) move_block_via_load_store(&myDst, src, len, align); else if (len == 8 && align == 8) move_block_via_load_store(&myDst, src, len, align); else if (len <= 16 || (copts.optimize_for_size == 0 && len <= 64)) move_block_via_load_store_sequence(&myDst, src, len, align); else move_block_via_inline_loop(&myDst, src, len, align); } static void load_word_of_small_struct(short dstReg, short srcReg, Operand *opnd, SInt32 offset, SInt32 len, SInt32 align) { short tmpReg; short extra = 0; switch (len) { case 1: tmpReg = used_virtual_registers[RegClass_GPR]++; load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); setpcodeflags(opnd->flags); emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); setpcodeflags(opnd->flags); break; case 2: case 3: if (align > 1) { tmpReg = used_virtual_registers[RegClass_GPR]++; load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset); extra += 2; setpcodeflags(opnd->flags); emitpcode(PC_RLWINM, dstReg, tmpReg, 16, 0, 15); setpcodeflags(opnd->flags); } else { tmpReg = used_virtual_registers[RegClass_GPR]++; load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); setpcodeflags(opnd->flags); emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); setpcodeflags(opnd->flags); load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 1); extra += 2; setpcodeflags(opnd->flags); emitpcode(PC_RLWIMI, dstReg, tmpReg, 16, 8, 15); setpcodeflags(opnd->flags); } if (len == 3) { load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + extra); setpcodeflags(opnd->flags); emitpcode(PC_RLWIMI, dstReg, tmpReg, 8, 16, 23); setpcodeflags(opnd->flags); } break; case 4: if (align > 2) { load_store_register(PC_LWZ, dstReg, srcReg, opnd->object, offset); setpcodeflags(opnd->flags); } else if (align > 1) { tmpReg = used_virtual_registers[RegClass_GPR]++; load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset); setpcodeflags(opnd->flags); emitpcode(PC_RLWINM, dstReg, tmpReg, 16, 0, 15); setpcodeflags(opnd->flags); load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset + 2); setpcodeflags(opnd->flags); emitpcode(PC_RLWIMI, dstReg, tmpReg, 0, 16, 31); setpcodeflags(opnd->flags); } else { tmpReg = used_virtual_registers[RegClass_GPR]++; load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); setpcodeflags(opnd->flags); emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); setpcodeflags(opnd->flags); load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 1); setpcodeflags(opnd->flags); emitpcode(PC_RLWIMI, dstReg, tmpReg, 16, 8, 15); setpcodeflags(opnd->flags); load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 2); setpcodeflags(opnd->flags); emitpcode(PC_RLWIMI, dstReg, tmpReg, 8, 16, 23); setpcodeflags(opnd->flags); load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 3); setpcodeflags(opnd->flags); emitpcode(PC_RLWIMI, dstReg, tmpReg, 0, 24, 31); setpcodeflags(opnd->flags); } break; } } void load_small_block_into_reg(short dstReg, Operand *srcOpnd, Type *type, SInt32 align) { short finalReg; short tmpReg; SInt32 absAddress; coerce_to_addressable(srcOpnd); if (srcOpnd->optype == OpndType_IndirectGPR_Indexed) { CError_FATAL(557); tmpReg = used_virtual_registers[RegClass_GPR]++; load_address(tmpReg, srcOpnd); srcOpnd->optype = OpndType_IndirectGPR_ImmOffset; srcOpnd->reg = tmpReg; srcOpnd->object = NULL; srcOpnd->immOffset = 0; } if (copts.misaligned_mem_access) align = 4; switch (srcOpnd->optype) { case OpndType_GPRPair: return; case OpndType_GPR: return; case OpndType_GPR_ImmOffset: finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; add_immediate(finalReg, srcOpnd->reg, srcOpnd->object, srcOpnd->immOffset); break; case OpndType_GPR_Indexed: finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; emitpcode(PC_ADD, finalReg, srcOpnd->reg, srcOpnd->regOffset); break; case OpndType_Absolute: finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; absAddress = srcOpnd->immediate; if (FITS_IN_SHORT(absAddress)) { emitpcode(PC_LI, finalReg, absAddress); } else { tmpReg = finalReg; if (copts.optimizationlevel > 1 && absAddress) tmpReg = used_virtual_registers[RegClass_GPR]++; emitpcode(PC_LIS, tmpReg, 0, HIGH_PART(absAddress)); if (absAddress) emitpcode(PC_ADDI, finalReg, tmpReg, 0, LOW_PART(absAddress)); } break; case OpndType_IndirectGPR_ImmOffset: finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; load_word_of_small_struct(finalReg, srcOpnd->reg, srcOpnd, srcOpnd->immOffset, type->size, align); break; default: CError_FATAL(606); } srcOpnd->optype = OpndType_GPR; srcOpnd->reg = finalReg; } void load_small_block_into_reg_pair(short dstRegLo, short dstRegHi, Operand *srcOpnd, Type *type, SInt32 align) { short finalRegLo; short finalRegHi; short tmpRegLo; short tmpRegHi; short tmpReg; SInt32 absAddress; finalRegHi = -1; coerce_to_addressable(srcOpnd); if (srcOpnd->optype == OpndType_IndirectGPR_Indexed) { CError_FATAL(624); tmpReg = used_virtual_registers[RegClass_GPR]++; load_address(tmpReg, srcOpnd); srcOpnd->optype = OpndType_IndirectGPR_ImmOffset; srcOpnd->reg = tmpReg; srcOpnd->object = NULL; srcOpnd->immOffset = 0; } if (copts.misaligned_mem_access) align = 4; switch (srcOpnd->optype) { case OpndType_GPRPair: if (dstRegLo != 0 && dstRegHi == 0) dstRegHi = used_virtual_registers[RegClass_GPR]++; if (dstRegHi != 0 && dstRegLo == 0) dstRegLo = used_virtual_registers[RegClass_GPR]++; if (srcOpnd->reg != dstRegLo || srcOpnd->regHi != dstRegHi) { tmpRegLo = dstRegLo ? dstRegLo : srcOpnd->reg; tmpRegHi = dstRegHi ? dstRegHi : srcOpnd->regHi; if (tmpRegLo != srcOpnd->reg) { if (tmpRegLo == srcOpnd->regHi) { CError_ASSERT(657, tmpRegLo != tmpRegHi); emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); } else { emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); if (srcOpnd->regHi != tmpRegHi) emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); } } else if (tmpRegHi != srcOpnd->regHi) { if (tmpRegHi == srcOpnd->reg) { CError_ASSERT(671, tmpRegLo != tmpRegHi); emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); } else { emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); if (srcOpnd->reg != tmpRegLo) emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); } } } finalRegLo = srcOpnd->reg; finalRegHi = srcOpnd->regHi; break; case OpndType_GPR: CError_FATAL(688); break; case OpndType_GPR_ImmOffset: CError_FATAL(691); break; case OpndType_GPR_Indexed: CError_FATAL(694); break; case OpndType_Absolute: finalRegLo = dstRegLo ? dstRegLo : used_virtual_registers[RegClass_GPR]++; absAddress = srcOpnd->immediate; if (FITS_IN_SHORT(absAddress)) { emitpcode(PC_LI, finalRegLo, absAddress); } else { tmpReg = finalRegLo; if (copts.optimizationlevel > 1 && absAddress) tmpReg = used_virtual_registers[RegClass_GPR]++; emitpcode(PC_LIS, tmpReg, 0, HIGH_PART(absAddress)); if (absAddress) emitpcode(PC_ADDI, finalRegLo, tmpReg, 0, LOW_PART(absAddress)); } finalRegHi = dstRegHi ? dstRegHi : used_virtual_registers[RegClass_GPR]++; if (is_unsigned(type) || absAddress >= 0) load_immediate(finalRegHi, 0); else load_immediate(finalRegHi, -1); break; case OpndType_IndirectGPR_ImmOffset: finalRegLo = dstRegLo ? dstRegLo : used_virtual_registers[RegClass_GPR]++; finalRegHi = dstRegHi ? dstRegHi : used_virtual_registers[RegClass_GPR]++; if (srcOpnd->reg == finalRegHi) { if (srcOpnd->reg == finalRegLo) { CError_FATAL(726); } else { load_word_of_small_struct( finalRegLo, srcOpnd->reg, srcOpnd, srcOpnd->immOffset + low_offset, type->size - 4, align); load_word_of_small_struct( finalRegHi, srcOpnd->reg, srcOpnd, srcOpnd->immOffset + high_offset, 4, align); } } else { load_word_of_small_struct( finalRegHi, srcOpnd->reg, srcOpnd, srcOpnd->immOffset + high_offset, 4, align); load_word_of_small_struct( finalRegLo, srcOpnd->reg, srcOpnd, srcOpnd->immOffset + low_offset, type->size - 4, align); } break; default: CError_FATAL(737); } if (finalRegHi == -1) { CError_FATAL(741); } else { srcOpnd->optype = OpndType_GPRPair; srcOpnd->reg = finalRegLo; srcOpnd->regHi = finalRegHi; } } static void store_word_of_small_struct(short srcReg, short dstReg, Operand *opnd, SInt32 offset, SInt32 len, SInt32 align) { short tmpReg; short extra = 0; switch (len) { case 1: tmpReg = used_virtual_registers[RegClass_GPR]++; emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); setpcodeflags(opnd->flags); load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); setpcodeflags(opnd->flags); break; case 2: case 3: if (align > 1) { tmpReg = used_virtual_registers[RegClass_GPR]++; emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 16, 31); setpcodeflags(opnd->flags); load_store_register(PC_STH, tmpReg, dstReg, opnd->object, offset); extra += 2; setpcodeflags(opnd->flags); } else { tmpReg = used_virtual_registers[RegClass_GPR]++; emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); setpcodeflags(opnd->flags); load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); setpcodeflags(opnd->flags); emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 24, 31); setpcodeflags(opnd->flags); load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 1); extra += 2; setpcodeflags(opnd->flags); } if (len == 3) { emitpcode(PC_RLWINM, tmpReg, srcReg, 24, 24, 31); setpcodeflags(opnd->flags); load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + extra); setpcodeflags(opnd->flags); } break; case 4: if (align > 2) { load_store_register(PC_STW, srcReg, dstReg, opnd->object, offset); setpcodeflags(opnd->flags); } else if (align > 1) { tmpReg = used_virtual_registers[RegClass_GPR]++; emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 16, 31); setpcodeflags(opnd->flags); load_store_register(PC_STH, tmpReg, dstReg, opnd->object, offset); setpcodeflags(opnd->flags); load_store_register(PC_STH, srcReg, dstReg, opnd->object, offset + 2); setpcodeflags(opnd->flags); } else { tmpReg = used_virtual_registers[RegClass_GPR]++; emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); setpcodeflags(opnd->flags); load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); setpcodeflags(opnd->flags); emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 24, 31); setpcodeflags(opnd->flags); load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 1); setpcodeflags(opnd->flags); emitpcode(PC_RLWINM, tmpReg, srcReg, 24, 24, 31); setpcodeflags(opnd->flags); load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 2); setpcodeflags(opnd->flags); load_store_register(PC_STB, srcReg, dstReg, opnd->object, offset + 3); setpcodeflags(opnd->flags); } break; } } void store_small_block_from_reg(short srcReg, Operand *dstOpnd, Type *type, SInt32 align) { short tmpReg; coerce_to_addressable(dstOpnd); if (dstOpnd->optype == OpndType_IndirectGPR_Indexed) { CError_FATAL(839); tmpReg = used_virtual_registers[RegClass_GPR]++; load_address(tmpReg, dstOpnd); dstOpnd->optype = OpndType_IndirectGPR_ImmOffset; dstOpnd->reg = tmpReg; dstOpnd->object = NULL; dstOpnd->immOffset = 0; } if (copts.misaligned_mem_access) align = 4; store_word_of_small_struct(srcReg, dstOpnd->reg, dstOpnd, dstOpnd->immOffset, type->size, align); } void store_small_block_from_reg_pair(short srcRegLo, short srcRegHi, Operand *dstOpnd, Type *type, SInt32 align) { short tmpReg; coerce_to_addressable(dstOpnd); if (dstOpnd->optype == OpndType_IndirectGPR_Indexed) { CError_FATAL(860); tmpReg = used_virtual_registers[RegClass_GPR]++; load_address(tmpReg, dstOpnd); dstOpnd->optype = OpndType_IndirectGPR_ImmOffset; dstOpnd->reg = tmpReg; dstOpnd->object = NULL; dstOpnd->immOffset = 0; } if (copts.misaligned_mem_access) align = 4; store_word_of_small_struct( srcRegLo, dstOpnd->reg, dstOpnd, dstOpnd->immOffset + low_offset, type->size - 4, align); store_word_of_small_struct( srcRegHi, dstOpnd->reg, dstOpnd, dstOpnd->immOffset + high_offset, 4, align); }