summaryrefslogtreecommitdiff
path: root/compiler_and_linker/unsorted/StructMoves.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/StructMoves.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/unsorted/StructMoves.c')
-rw-r--r--compiler_and_linker/unsorted/StructMoves.c792
1 files changed, 0 insertions, 792 deletions
diff --git a/compiler_and_linker/unsorted/StructMoves.c b/compiler_and_linker/unsorted/StructMoves.c
deleted file mode 100644
index 7c28b88..0000000
--- a/compiler_and_linker/unsorted/StructMoves.c
+++ /dev/null
@@ -1,792 +0,0 @@
-#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.optimizesize == 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);
-}