summaryrefslogtreecommitdiff
path: root/compiler_and_linker/unsorted/PCodeAssembly.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/PCodeAssembly.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/PCodeAssembly.c')
-rw-r--r--compiler_and_linker/unsorted/PCodeAssembly.c1613
1 files changed, 0 insertions, 1613 deletions
diff --git a/compiler_and_linker/unsorted/PCodeAssembly.c b/compiler_and_linker/unsorted/PCodeAssembly.c
deleted file mode 100644
index 368f8c5..0000000
--- a/compiler_and_linker/unsorted/PCodeAssembly.c
+++ /dev/null
@@ -1,1613 +0,0 @@
-#include "compiler/PCodeAssembly.h"
-#include "compiler/CError.h"
-#include "compiler/CFunc.h"
-#include "compiler/CMangler.h"
-#include "compiler/CParser.h"
-#include "compiler/CodeGen.h"
-#include "compiler/ObjGenMachO.h"
-#include "compiler/PCode.h"
-#include "compiler/PCodeInfo.h"
-#include "compiler/PCodeListing.h"
-#include "compiler/PPCError.h"
-#include "compiler/RegisterInfo.h"
-#include "compiler/StackFrame.h"
-#include "compiler/TOC.h"
-#include "compiler/objects.h"
-
-static UInt32 codebase;
-
-static SInt32 pcode_update_mem_labeldiff_imm(PCode *instr, const PCodeArg *op, WeirdOperand *wop) {
- SInt32 offset;
- Object *object;
- UInt8 arg;
-
- if (op->kind == PCOp_MEMORY) {
- object = op->data.mem.obj;
- offset = op->data.mem.offset;
- switch (object->datatype) {
- case DLOCAL:
- switch ((UInt8) op->arg) {
- case RefType_1:
- offset += local_offset_16(object);
- break;
- case RefType_D:
- offset = local_offset_lo(object, offset);
- break;
- case RefType_C:
- offset = local_offset_ha(object, offset);
- break;
- default:
- CError_FATAL(83);
- }
- break;
- case DDATA:
- case DFUNC:
- case DVFUNC:
- case DNONLAZYPTR:
- switch ((UInt8) op->arg) {
- case RefType_6:
- wop->type = MW_RELOC_5_LO16;
- break;
- case RefType_2:
- wop->type = MW_RELOC_3;
- break;
- case RefType_3:
- wop->type = MW_RELOC_4;
- break;
- case RefType_8:
- wop->type = MW_RELOC_7_HA16;
- break;
- case RefType_7:
- wop->type = MW_RELOC_6_HI16;
- break;
- default:
- CError_FATAL(135);
- }
-
- wop->x2 = object;
- CError_ASSERT(144, offset == 0);
- break;
- default:
- CError_FATAL(164);
- }
- } else if (op->kind == PCOp_LABELDIFF) {
- arg = op->arg;
-
- offset = op->data.labeldiff.labelA->block->codeOffset - op->data.labeldiff.labelB->block->codeOffset;
- offset += op->data.labeldiff.offset;
- if (arg == 1)
- offset = -offset;
-
- if (offset > 0x7FFF)
- PPCError_Error(PPCErrorStr109);
- else if (offset < -0x8000)
- PPCError_Error(PPCErrorStr109);
- } else if (op->kind == PCOp_IMMEDIATE) {
- offset = op->data.imm.value;
- } else {
- CError_FATAL(193);
- }
-
- return offset;
-}
-
-UInt32 assemblepcode(PCode *instr, UInt32 offset, WeirdOperand *wop) {
- UInt32 bits;
-
- bits = opcodeinfo[instr->op].insn;
- wop->type = -1;
- wop->x6 = 0;
-
- switch (instr->op) {
- case PC_BL: {
- int flag = PCODE_FLAG_SET_T(instr) & fAbsolute;
- if (instr->args[0].kind == PCOp_MEMORY) {
- bits |= instr->args[0].data.mem.offset & 0x3FFFFFC;
- wop->type = MW_RELOC_2_BR24;
- wop->x2 = instr->args[0].data.mem.obj;
- if (flag == 0)
- wop->type = MW_RELOC_2_BR24;
- else
- CError_FATAL(246);
- } else if (instr->args[0].kind == PCOp_IMMEDIATE) {
- bits |= instr->args[0].data.imm.value & 0x3FFFFFC;
- if (flag)
- bits |= 2;
- } else {
- bits |= (instr->args[0].data.label.label->block->codeOffset - offset) & 0x3FFFFFC;
- if (flag)
- CError_FATAL(261);
- }
- break;
- }
-
- case PC_B: {
- int flag = PCODE_FLAG_SET_T(instr) & fAbsolute;
- if (instr->args[0].kind == PCOp_MEMORY) {
- bits |= instr->args[0].data.mem.offset & 0x3FFFFFC;
- wop->x2 = instr->args[0].data.mem.obj;
- if (flag == 0)
- wop->type = MW_RELOC_2_BR24;
- else
- CError_FATAL(288);
- } else if (instr->args[0].kind == PCOp_IMMEDIATE) {
- bits |= instr->args[0].data.imm.value & 0x3FFFFFC;
- if (flag)
- bits |= 2;
- } else {
- bits |= (instr->args[0].data.label.label->block->codeOffset - offset) & 0x3FFFFFC;
- if (flag)
- CError_FATAL(302);
- }
- if (PCODE_FLAG_SET_T(instr) & fLink)
- bits |= 1;
- break;
- }
-
- case PC_BDNZ:
- case PC_BDZ: {
- int flag = PCODE_FLAG_SET_T(instr) & fAbsolute;
- if (instr->args[0].kind == PCOp_MEMORY) {
- bits |= instr->args[0].data.mem.offset & 0xFFFC;
- wop->x2 = instr->args[0].data.mem.obj;
- if (flag == 0)
- wop->type = MW_RELOC_8;
- else
- CError_FATAL(333);
- } else {
- SInt32 value;
- if (instr->args[0].kind == PCOp_IMMEDIATE)
- value = instr->args[0].data.imm.value;
- else
- value = instr->args[0].data.label.label->block->codeOffset - offset;
-
- bits |= value & 0xFFFF;
- if (value < 0) {
- if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken)
- bits |= 0x200000u;
- } else {
- if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
- bits |= 0x200000u;
- }
- }
- if (PCODE_FLAG_SET_T(instr) & fLink)
- bits |= 1;
- break;
- }
-
- case PC_BC: {
- int flag = PCODE_FLAG_SET_T(instr) & fAbsolute;
- bits |= (instr->args[0].data.imm.value & 31) << 21;
- bits |= ((instr->args[1].data.reg.reg * 4 + instr->args[2].data.imm.value) & 31) << 16;
-
- if (instr->args[3].kind == PCOp_MEMORY) {
- bits |= instr->args[3].data.mem.offset & 0xFFFC;
- wop->x2 = instr->args[3].data.mem.obj;
- if (flag == 0)
- wop->type = MW_RELOC_8;
- else
- CError_FATAL(387);
- } else {
- SInt32 value;
- if (instr->args[3].kind == PCOp_IMMEDIATE)
- value = instr->args[3].data.imm.value;
- else
- value = instr->args[3].data.label.label->block->codeOffset - offset;
-
- bits |= value & 0xFFFF;
- if (value < 0) {
- if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken)
- bits |= 0x200000u;
- } else {
- if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
- bits |= 0x200000u;
- }
- }
- if (PCODE_FLAG_SET_T(instr) & fLink)
- bits |= 1;
- break;
- }
-
- case PC_BT:
- case PC_BF:
- case PC_BDNZT:
- case PC_BDNZF:
- case PC_BDZT:
- case PC_BDZF: {
- int flag = PCODE_FLAG_SET_T(instr) & fAbsolute;
- bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 16;
-
- if (instr->args[2].kind == PCOp_MEMORY) {
- bits |= instr->args[2].data.mem.offset & 0xFFFC;
- wop->x2 = instr->args[2].data.mem.obj;
- if (flag == 0)
- wop->type = MW_RELOC_8;
- else
- CError_FATAL(446);
- } else {
- SInt32 value;
- if (instr->args[2].kind == PCOp_IMMEDIATE) {
- value = instr->args[2].data.imm.value;
- if (flag)
- bits |= 2;
- } else {
- value = instr->args[2].data.label.label->block->codeOffset - offset;
- CError_ASSERT(458, !flag);
- }
-
- bits |= value & 0xFFFF;
-
- if (value < 0) {
- if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken)
- bits |= 0x200000u;
- } else {
- if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
- bits |= 0x200000u;
- }
- }
-
- if (PCODE_FLAG_SET_T(instr) & fLink)
- bits |= 1;
- break;
- }
-
- case PC_BTLR:
- case PC_BTCTR:
- case PC_BFLR:
- case PC_BFCTR:
- bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 16;
- if (PCODE_FLAG_SET_T(instr) & fLink)
- bits |= 1;
- if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
- bits |= 0x200000u;
- break;
-
- case PC_BCLR:
- case PC_BCCTR:
- bits |= instr->args[0].data.imm.value << 21;
- bits |= ((instr->args[1].data.reg.reg * 4 + instr->args[2].data.imm.value) & 31) << 16;
- case PC_BLR:
- case PC_BCTR:
- case PC_BCTRL:
- case PC_BLRL:
- if (PCODE_FLAG_SET_T(instr) & fLink)
- bits |= 1;
- if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
- bits |= 0x200000u;
- break;
-
- case PC_CRAND:
- case PC_CRANDC:
- case PC_CREQV:
- case PC_CRNAND:
- case PC_CRNOR:
- case PC_CROR:
- case PC_CRORC:
- case PC_CRXOR:
- bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 21;
- bits |= ((instr->args[2].data.reg.reg * 4 + instr->args[3].data.imm.value) & 31) << 16;
- bits |= ((instr->args[4].data.reg.reg * 4 + instr->args[5].data.imm.value) & 31) << 11;
- break;
-
- case PC_MCRF:
- bits |= instr->args[0].data.reg.reg << 23;
- bits |= instr->args[1].data.reg.reg << 18;
- break;
-
- case PC_LBZ:
- case PC_LBZU:
- case PC_LHZ:
- case PC_LHZU:
- case PC_LHA:
- case PC_LHAU:
- case PC_LWZ:
- case PC_LWZU:
- case PC_LMW:
- case PC_STB:
- case PC_STBU:
- case PC_STH:
- case PC_STHU:
- case PC_STW:
- case PC_STWU:
- case PC_STMW:
- case PC_LFS:
- case PC_LFSU:
- case PC_LFD:
- case PC_LFDU:
- case PC_STFS:
- case PC_STFSU:
- case PC_STFD:
- case PC_STFDU:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF;
- break;
-
- case PC_LBZX:
- case PC_LBZUX:
- case PC_LHZX:
- case PC_LHZUX:
- case PC_LHAX:
- case PC_LHAUX:
- case PC_LHBRX:
- case PC_LWZX:
- case PC_LWZUX:
- case PC_LWBRX:
- case PC_STBX:
- case PC_STBUX:
- case PC_STHX:
- case PC_STHUX:
- case PC_STHBRX:
- case PC_STWX:
- case PC_STWUX:
- case PC_STWBRX:
- case PC_LFSX:
- case PC_LFSUX:
- case PC_LFDX:
- case PC_LFDUX:
- case PC_STFSX:
- case PC_STFSUX:
- case PC_STFDX:
- case PC_STFDUX:
- case PC_LWARX:
- case PC_LSWX:
- case PC_STFIWX:
- case PC_STSWX:
- case PC_STWCX:
- case PC_ECIWX:
- case PC_ECOWX:
- case PC_DCREAD:
- case PC_TLBSX:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_DCBF:
- case PC_DCBST:
- case PC_DCBT:
- case PC_DCBTST:
- case PC_DCBZ:
- case PC_DCBI:
- case PC_ICBI:
- case PC_DCCCI:
- case PC_ICBT:
- case PC_ICCCI:
- case PC_ICREAD:
- case PC_DCBA:
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 11;
- break;
-
- case PC_ADD:
- case PC_ADDC:
- case PC_ADDE:
- case PC_DIVW:
- case PC_DIVWU:
- case PC_MULHW:
- case PC_MULHWU:
- case PC_MULLW:
- case PC_SUBF:
- case PC_SUBFC:
- case PC_SUBFE:
- bits |= instr->args[2].data.reg.reg << 11;
- case PC_ADDME:
- case PC_ADDZE:
- case PC_NEG:
- case PC_SUBFME:
- case PC_SUBFZE:
- case PC_MFROM:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- if (PCODE_FLAG_SET_F(instr) & fOverflow)
- bits |= 0x400;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_ADDI:
- case PC_ADDIC:
- case PC_ADDICR:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF;
- break;
-
- case PC_ADDIS:
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF;
- break;
-
- case PC_MULLI:
- case PC_SUBFIC:
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[2].data.imm.value & 0xFFFF;
- break;
-
- case PC_LI:
- case PC_LIS:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[1], wop) & 0xFFFF;
- break;
-
- case PC_ANDI:
- case PC_ANDIS:
- case PC_ORI:
- case PC_ORIS:
- case PC_XORI:
- case PC_XORIS:
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF;
- break;
-
- case PC_AND:
- case PC_OR:
- case PC_XOR:
- case PC_NAND:
- case PC_NOR:
- case PC_EQV:
- case PC_ANDC:
- case PC_ORC:
- case PC_SLW:
- case PC_SRW:
- case PC_SRAW:
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= instr->args[2].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_EXTSH:
- case PC_EXTSB:
- case PC_CNTLZW:
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 21;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_MR:
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_NOT:
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_SRAWI:
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= (instr->args[2].data.imm.value & 31) << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_RLWINM:
- case PC_RLWIMI:
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= (instr->args[2].data.imm.value & 31) << 11;
- bits |= (instr->args[3].data.imm.value & 31) << 6;
- bits |= (instr->args[4].data.imm.value & 31) << 1;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_RLWNM:
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= instr->args[2].data.reg.reg << 11;
- bits |= (instr->args[3].data.imm.value & 31) << 6;
- bits |= (instr->args[4].data.imm.value & 31) << 1;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_CMP:
- case PC_CMPL:
- bits |= instr->args[0].data.reg.reg << 23;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- break;
-
- case PC_CMPI:
- case PC_CMPLI:
- bits |= instr->args[0].data.reg.reg << 23;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.imm.value & 0xFFFF;
- break;
-
- case PC_MTXER:
- case PC_MTCTR:
- case PC_MTLR:
- case PC_MTMSR:
- case PC_MFMSR:
- case PC_MFXER:
- case PC_MFCTR:
- case PC_MFLR:
- case PC_MFCR:
- bits |= instr->args[0].data.reg.reg << 21;
- break;
-
- case PC_MFFS:
- bits |= instr->args[0].data.reg.reg << 21;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_MTCRF:
- bits |= instr->args[0].data.imm.value << 12;
- bits |= instr->args[1].data.reg.reg << 21;
- break;
-
- case PC_MTFSF:
- bits |= (instr->args[0].data.imm.value & 0xFF) << 17;
- bits |= instr->args[1].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_FMR:
- case PC_FABS:
- case PC_FNEG:
- case PC_FNABS:
- case PC_FRES:
- case PC_FRSQRTE:
- case PC_FRSP:
- case PC_FCTIW:
- case PC_FCTIWZ:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_FADD:
- case PC_FADDS:
- case PC_FSUB:
- case PC_FSUBS:
- case PC_FDIV:
- case PC_FDIVS:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_FMADD:
- case PC_FMADDS:
- case PC_FMSUB:
- case PC_FMSUBS:
- case PC_FNMADD:
- case PC_FNMADDS:
- case PC_FNMSUB:
- case PC_FNMSUBS:
- case PC_FSEL:
- bits |= instr->args[3].data.reg.reg << 11;
- case PC_FMUL:
- case PC_FMULS:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 6;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_FCMPU:
- case PC_FCMPO:
- bits |= instr->args[0].data.reg.reg << 23;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- break;
-
- case PC_MTSPR:
- if (instr->args[0].kind == PCOp_REGISTER) {
- CError_ASSERT(1027, instr->args[0].arg == RegClass_SPR);
- CError_ASSERT(1028, instr->args[0].data.reg.reg < 4);
- bits |= ((spr_to_sysreg[instr->args[0].data.reg.reg] & 0x1F) << 16) +
- ((spr_to_sysreg[instr->args[0].data.reg.reg] & 0x3E0) << 6);
- } else if (instr->args[0].kind == PCOp_SYSREG && instr->args[0].arg == 0) {
- bits |= ((instr->args[0].data.reg.reg & 0x1F) << 16) +
- ((instr->args[0].data.reg.reg & 0x3E0) << 6);
- } else {
- CError_FATAL(1033);
- }
-
- bits |= instr->args[1].data.reg.reg << 21;
- break;
-
- case PC_MTDCR:
- if (instr->args[0].kind == PCOp_IMMEDIATE) {
- bits |= ((instr->args[0].data.imm.value & 0x1F) << 16) +
- ((instr->args[0].data.imm.value & 0x3E0) << 6);
- } else {
- CError_FATAL(1042);
- }
-
- bits |= instr->args[1].data.reg.reg << 21;
- break;
-
- case PC_MFSPR:
- bits |= instr->args[0].data.reg.reg << 21;
-
- if (instr->args[1].kind == PCOp_REGISTER && instr->args[1].arg == RegClass_SPR) {
- CError_ASSERT(1055, instr->args[1].data.reg.reg < 4);
- bits |= ((spr_to_sysreg[instr->args[1].data.reg.reg] & 0x1F) << 16) +
- ((spr_to_sysreg[instr->args[1].data.reg.reg] & 0x3E0) << 6);
- } else if (instr->args[1].kind == PCOp_SYSREG && instr->args[1].arg == 0) {
- bits |= ((instr->args[1].data.reg.reg & 0x1F) << 16) +
- ((instr->args[1].data.reg.reg & 0x3E0) << 6);
- } else {
- CError_FATAL(1060);
- }
- break;
-
- case PC_MFDCR:
- bits |= instr->args[0].data.reg.reg << 21;
-
- if (instr->args[1].kind == PCOp_IMMEDIATE) {
- bits |= ((instr->args[1].data.imm.value & 0x1F) << 16) +
- ((instr->args[1].data.imm.value & 0x3E0) << 6);
- } else {
- CError_FATAL(1069);
- }
- break;
-
- case PC_LSWI:
- case PC_STSWI:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= (instr->args[2].data.imm.value & 31) << 11;
- break;
-
- case PC_MCRFS:
- bits |= (instr->args[1].data.imm.value & 7) << 18;
- case PC_MCRXR:
- bits |= instr->args[0].data.reg.reg << 23;
- break;
-
- case PC_MFTB:
- bits |= instr->args[0].data.reg.reg << 21;
- if (instr->args[1].kind == PCOp_SYSREG && instr->args[1].arg == 0) {
- if (instr->args[1].data.reg.reg == 284)
- bits |= 0xC4000u;
- else if (instr->args[1].data.reg.reg == 285)
- bits |= 0xD4000u;
- else
- CError_FATAL(1100);
- } else {
- CError_FATAL(1103);
- }
- break;
-
- case PC_MTSR:
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= (instr->args[0].data.imm.value & 15) << 16;
- break;
-
- case PC_MFSR:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= (instr->args[1].data.imm.value & 15) << 16;
- break;
-
- case PC_MFSRIN:
- case PC_MTSRIN:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 11;
- break;
-
- case PC_MTFSB0:
- case PC_MTFSB1:
- bits |= (instr->args[0].data.imm.value & 31) << 21;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_MTFSFI:
- bits |= instr->args[0].data.reg.reg << 23;
- bits |= (instr->args[1].data.imm.value & 15) << 12;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_FSQRT:
- case PC_FSQRTS:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_TLBIE:
- case PC_TLBLD:
- case PC_TLBLI:
- bits |= instr->args[0].data.reg.reg << 11;
- break;
-
- case PC_TW:
- bits |= (instr->args[0].data.imm.value & 31) << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- break;
-
- case PC_TWI:
- bits |= (instr->args[0].data.imm.value & 31) << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.imm.value & 0xFFFF;
- break;
-
- case PC_OPWORD:
- CError_ASSERT(1176, instr->args[0].kind != PCOp_MEMORY);
- bits = pcode_update_mem_labeldiff_imm(instr, &instr->args[0], wop);
- break;
-
- case PC_MASKG:
- case PC_MASKIR:
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_LSCBX:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_DIV:
- case PC_DIVS:
- case PC_DOZ:
- case PC_MUL:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fOverflow)
- bits |= 0x400;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_NABS:
- case PC_ABS:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- if (PCODE_FLAG_SET_F(instr) & fOverflow)
- bits |= 0x400;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_CLCS:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_DOZI:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.imm.value & 0xFFFF;
- break;
-
- case PC_RLMI:
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- bits |= (instr->args[3].data.imm.value & 31) << 6;
- bits |= (instr->args[4].data.imm.value & 31) << 1;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_SLE:
- case PC_SLEQ:
- case PC_SLLQ:
- case PC_SLQ:
- case PC_SRAQ:
- case PC_SRE:
- case PC_SREA:
- case PC_SREQ:
- case PC_SRLQ:
- case PC_SRQ:
- case PC_RRIB:
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_SLIQ:
- case PC_SLLIQ:
- case PC_SRAIQ:
- case PC_SRIQ:
- case PC_SRLIQ:
- bits |= instr->args[1].data.reg.reg << 21;
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= (instr->args[2].data.imm.value & 31) << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 1;
- break;
-
- case PC_TLBRE:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= (instr->args[2].data.imm.value & 1) << 11;
- break;
-
- case PC_TLBWE:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= (instr->args[2].data.imm.value & 1) << 11;
- break;
-
- case PC_WRTEE:
- bits |= instr->args[0].data.reg.reg << 21;
- break;
-
- case PC_WRTEEI:
- bits |= instr->args[0].data.imm.value << 15;
- break;
-
- case PC_DSTT:
- case PC_DSTSTT:
- bits |= 0x2000000u;
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 11;
- bits |= (instr->args[2].data.imm.value & 3) << 21;
- break;
-
- case PC_DST:
- case PC_DSTST:
- bits |= (instr->args[3].data.imm.value & 1) << 25;
- bits |= instr->args[0].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 11;
- bits |= (instr->args[2].data.imm.value & 3) << 21;
- break;
-
- case PC_DSSALL:
- bits |= 0x2000000u;
- break;
-
- case PC_DSS:
- bits |= (instr->args[1].data.imm.value & 1) << 25;
- bits |= (instr->args[0].data.imm.value & 3) << 21;
- break;
-
- case PC_LVEBX:
- case PC_LVEHX:
- case PC_LVEWX:
- case PC_LVSL:
- case PC_LVSR:
- case PC_LVX:
- case PC_LVXL:
- case PC_STVEBX:
- case PC_STVEHX:
- case PC_STVEWX:
- case PC_STVX:
- case PC_STVXL:
- case PC_VADDCUW:
- case PC_VADDFP:
- case PC_VADDSBS:
- case PC_VADDSHS:
- case PC_VADDSWS:
- case PC_VADDUBM:
- case PC_VADDUBS:
- case PC_VADDUHM:
- case PC_VADDUHS:
- case PC_VADDUWM:
- case PC_VADDUWS:
- case PC_VAND:
- case PC_VANDC:
- case PC_VAVGSB:
- case PC_VAVGSH:
- case PC_VAVGSW:
- case PC_VAVGUB:
- case PC_VAVGUH:
- case PC_VAVGUW:
- case PC_VMAXFP:
- case PC_VMAXSB:
- case PC_VMAXSH:
- case PC_VMAXSW:
- case PC_VMAXUB:
- case PC_VMAXUH:
- case PC_VMAXUW:
- case PC_VMINFP:
- case PC_VMINSB:
- case PC_VMINSH:
- case PC_VMINSW:
- case PC_VMINUB:
- case PC_VMINUH:
- case PC_VMINUW:
- case PC_VMRGHB:
- case PC_VMRGHH:
- case PC_VMRGHW:
- case PC_VMRGLB:
- case PC_VMRGLH:
- case PC_VMRGLW:
- case PC_VMULESB:
- case PC_VMULESH:
- case PC_VMULEUB:
- case PC_VMULEUH:
- case PC_VMULOSB:
- case PC_VMULOSH:
- case PC_VMULOUB:
- case PC_VMULOUH:
- case PC_VNOR:
- case PC_VOR:
- case PC_VPKPX:
- case PC_VPKSHSS:
- case PC_VPKSHUS:
- case PC_VPKSWSS:
- case PC_VPKSWUS:
- case PC_VPKUHUM:
- case PC_VPKUHUS:
- case PC_VPKUWUM:
- case PC_VPKUWUS:
- case PC_VRLB:
- case PC_VRLH:
- case PC_VRLW:
- case PC_VSL:
- case PC_VSLB:
- case PC_VSLH:
- case PC_VSLO:
- case PC_VSLW:
- case PC_VSR:
- case PC_VSRAB:
- case PC_VSRAH:
- case PC_VSRAW:
- case PC_VSRB:
- case PC_VSRH:
- case PC_VSRO:
- case PC_VSRW:
- case PC_VSUBCUW:
- case PC_VSUBFP:
- case PC_VSUBSBS:
- case PC_VSUBSHS:
- case PC_VSUBSWS:
- case PC_VSUBUBM:
- case PC_VSUBUBS:
- case PC_VSUBUHM:
- case PC_VSUBUHS:
- case PC_VSUBUWM:
- case PC_VSUBUWS:
- case PC_VSUMSWS:
- case PC_VSUM2SWS:
- case PC_VSUM4SBS:
- case PC_VSUM4SHS:
- case PC_VSUM4UBS:
- case PC_VXOR:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- break;
-
- case PC_VCFSX:
- case PC_VCFUX:
- case PC_VCTSXS:
- case PC_VCTUXS:
- case PC_VSPLTB:
- case PC_VSPLTH:
- case PC_VSPLTW:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 11;
- bits |= (instr->args[2].data.imm.value & 31) << 16;
- break;
-
- case PC_VEXPTEFP:
- case PC_VLOGEFP:
- case PC_VREFP:
- case PC_VRFIM:
- case PC_VRFIN:
- case PC_VRFIP:
- case PC_VRFIZ:
- case PC_VRSQRTEFP:
- case PC_VUPKHPX:
- case PC_VUPKHSB:
- case PC_VUPKHSH:
- case PC_VUPKLPX:
- case PC_VUPKLSB:
- case PC_VUPKLSH:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 11;
- break;
-
- case PC_VCMPBFP:
- case PC_VCMPEQFP:
- case PC_VCMPEQUB:
- case PC_VCMPEQUH:
- case PC_VCMPEQUW:
- case PC_VCMPGEFP:
- case PC_VCMPGTFP:
- case PC_VCMPGTSB:
- case PC_VCMPGTSH:
- case PC_VCMPGTSW:
- case PC_VCMPGTUB:
- case PC_VCMPGTUH:
- case PC_VCMPGTUW:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- if (PCODE_FLAG_SET_F(instr) & fRecordBit)
- bits |= 0x400;
- break;
-
- case PC_VSPLTISB:
- case PC_VSPLTISH:
- case PC_VSPLTISW:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= (instr->args[1].data.imm.value & 31) << 16;
- break;
-
- case PC_VMHADDSHS:
- case PC_VMHRADDSHS:
- case PC_VMLADDUHM:
- case PC_VMSUMMBM:
- case PC_VMSUMSHM:
- case PC_VMSUMSHS:
- case PC_VMSUMUBM:
- case PC_VMSUMUHM:
- case PC_VMSUMUHS:
- case PC_VPERM:
- case PC_VSEL:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- bits |= instr->args[3].data.reg.reg << 6;
- break;
-
- case PC_VMADDFP:
- case PC_VNMSUBFP:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 6;
- bits |= instr->args[3].data.reg.reg << 11;
- break;
-
- case PC_VSLDOI:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[2].data.reg.reg << 11;
- bits |= (instr->args[3].data.imm.value & 15) << 6;
- break;
-
- case PC_VMR:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 11;
- break;
-
- case PC_VMRP:
- bits |= instr->args[0].data.reg.reg << 21;
- bits |= instr->args[1].data.reg.reg << 16;
- bits |= instr->args[1].data.reg.reg << 11;
- break;
-
- case PC_MFVSCR:
- bits |= instr->args[0].data.reg.reg << 21;
- break;
-
- case PC_MTVSCR:
- bits |= instr->args[0].data.reg.reg << 11;
- break;
-
- case PC_EIEIO:
- case PC_ISYNC:
- case PC_SYNC:
- case PC_RFI:
- case PC_NOP:
- case PC_SC:
- case PC_TLBIA:
- case PC_TLBSYNC:
- case PC_TRAP:
- case PC_DSA:
- case PC_ESA:
- case PC_RFCI:
- break;
-
- default:
- CError_FATAL(2203);
- }
-
- return CTool_EndianConvertWord32(bits);
-}
-
-static PCode *targetinstruction(PCodeLabel *label) {
- PCodeBlock *block = label->block;
- while (block->pcodeCount == 0)
- block = block->nextBlock;
- return block->firstPCode;
-}
-
-static void invertybit(PCode *instr, SInt32 value) {
- if (instr->op == PC_BC) {
- if (instr->args[0].data.imm.value & 1) {
- if (value < 0)
- instr->flags |= fBranchNotTaken;
- else
- instr->flags |= fBranchTaken;
- }
- } else if (instr->op == PC_BCCTR || instr->op == PC_BCLR) {
- if (instr->args[0].data.imm.value & 1)
- instr->flags |= fBranchTaken;
- }
-
- if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
- instr->flags = (instr->flags & ~fBranchTaken) | fBranchNotTaken;
- else if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken)
- instr->flags = (instr->flags & ~fBranchNotTaken) | fBranchTaken;
- else if (value < 0)
- instr->flags = (instr->flags & ~fBranchTaken) | fBranchNotTaken;
- else
- instr->flags = (instr->flags & ~fBranchNotTaken) | fBranchTaken;
-}
-
-static void insertlongbranches(SInt32 mask) {
- PCodeBlock *block;
- PCodeLabel *label;
- SInt32 i;
-
- i = 0;
- for (block = pcbasicblocks; block; block = block->nextBlock) {
- block->codeOffset = i;
- if (block->pcodeCount) {
- i += block->pcodeCount * 4;
- if (block->pcodeCount && (block->lastPCode->flags & fIsBranch))
- i += 4;
- }
- }
-
- for (block = pcbasicblocks; block; block = block->nextBlock) {
- if (block->pcodeCount && (block->lastPCode->flags & fIsBranch)) {
- switch (block->lastPCode->op) {
- case PC_BT:
- case PC_BF:
- i = block->codeOffset + ((block->pcodeCount - 1) * 4);
- if (block->lastPCode->args[2].kind == PCOp_LABEL) {
- label = block->lastPCode->args[2].data.label.label;
- i = label->block->codeOffset - i;
- if (i != ((SInt16) (i & mask))) {
- block->lastPCode->op = (block->lastPCode->op == PC_BT) ? PC_BF : PC_BT;
- block->lastPCode->args[2].data.label.label = block->nextBlock->labels;
- invertybit(block->lastPCode, i);
- appendpcode(block, makepcode(PC_B, label));
- }
- }
- break;
-
- case PC_BC:
- i = block->codeOffset + ((block->pcodeCount - 1) * 4);
- if (block->lastPCode->args[3].kind == PCOp_LABEL) {
- label = block->lastPCode->args[3].data.label.label;
- i = label->block->codeOffset - i;
- invertybit(block->lastPCode, i);
- if (i != ((SInt16) (i & mask))) {
- switch (block->lastPCode->args[0].data.imm.value & 30) {
- case 0:
- case 2:
- case 8:
- case 10:
- block->lastPCode->args[0].data.imm.value ^= 11;
- block->lastPCode->args[3].data.label.label = block->nextBlock->labels;
- break;
- case 16:
- case 18:
- block->lastPCode->args[0].data.imm.value ^= 3;
- block->lastPCode->args[3].data.label.label = block->nextBlock->labels;
- break;
- case 4:
- case 12:
- block->lastPCode->args[0].data.imm.value ^= 9;
- block->lastPCode->args[3].data.label.label = block->nextBlock->labels;
- break;
- case 20:
- deletepcode(block->lastPCode);
- break;
- default:
- CError_FATAL(2368);
- }
-
- appendpcode(block, makepcode(PC_B, label));
- }
- }
- break;
-
- case PC_BDNZ:
- case PC_BDZ:
- i = block->codeOffset + ((block->pcodeCount - 1) * 4);
- if (block->lastPCode->args[0].kind == PCOp_LABEL) {
- label = block->lastPCode->args[0].data.label.label;
- i = label->block->codeOffset - i;
- if (i != ((SInt16) (i & mask))) {
- switch (block->lastPCode->op) {
- case PC_BDZ:
- block->lastPCode->op = PC_BDNZ;
- break;
- case PC_BDNZ:
- block->lastPCode->op = PC_BDZ;
- break;
- default:
- CError_FATAL(2389);
- }
-
- block->lastPCode->args[0].data.label.label = block->nextBlock->labels;
- invertybit(block->lastPCode, i);
- appendpcode(block, makepcode(PC_B, label));
- }
- }
- break;
-
- case PC_BDNZT:
- case PC_BDNZF:
- case PC_BDZT:
- case PC_BDZF:
- i = block->codeOffset + ((block->pcodeCount - 1) * 4);
- if (block->lastPCode->args[2].kind == PCOp_LABEL) {
- label = block->lastPCode->args[2].data.label.label;
- i = label->block->codeOffset - i;
- if (i != ((SInt16) (i & mask))) {
- switch (block->lastPCode->op) {
- case PC_BDNZT:
- block->lastPCode->op = PC_BDZF;
- break;
- case PC_BDNZF:
- block->lastPCode->op = PC_BDZT;
- break;
- case PC_BDZT:
- block->lastPCode->op = PC_BDNZF;
- break;
- case PC_BDZF:
- block->lastPCode->op = PC_BDNZT;
- break;
- default:
- CError_FATAL(2420);
- }
-
- block->lastPCode->args[2].data.label.label = block->nextBlock->labels;
- invertybit(block->lastPCode, i);
- appendpcode(block, makepcode(PC_B, label));
- }
- }
- break;
-
- }
- }
- }
-}
-
-SInt32 optimizefinalbranches(SInt32 codesize) {
- PCodeBlock *block;
- PCode *instr;
- SInt32 offset;
- int changed;
- int deleted;
- PCodeLabel *label;
- PCode *target;
-
- do {
- changed = deleted = 0;
-
- for (block = pcbasicblocks; block; block = block->nextBlock) {
- if (block->pcodeCount == 0)
- continue;
-
- instr = block->lastPCode;
- if (!(instr->flags & fIsBranch))
- continue;
-
- offset = block->codeOffset + (block->pcodeCount - 1) * 4;
-
- if (instr->op == PC_B && instr->args[0].kind == PCOp_LABEL) {
- label = instr->args[0].data.label.label;
- target = targetinstruction(label);
-
- if (label->block->codeOffset == (offset + 4)) {
- deletepcode(instr);
- changed = deleted = 1;
- } else if (target->op == PC_B) {
- if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[0].data.label.label) {
- instr->args[0].data.label.label = target->args[0].data.label.label;
- changed = 1;
- }
- } else if (target->op == PC_BLR) {
- instr->op = PC_BLR;
- changed = 1;
- }
- continue;
- }
-
- if ((instr->op == PC_BT || instr->op == PC_BF) && instr->args[2].kind == PCOp_LABEL) {
- PCodeBlock *block2 = instr->block;
- label = instr->args[2].data.label.label;
- target = targetinstruction(label);
-
- if (label->block->codeOffset == (offset + 4)) {
- deletepcode(instr);
- changed = deleted = 1;
- } else if (target->op == PC_B) {
- if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[2].data.label.label) {
- instr->args[2].data.label.label = target->args[0].data.label.label;
- changed = 1;
- }
- } else if (copts.opt_bcc_lr_ctr) {
- if (target->op == PC_BLR) {
- if (instr->op == PC_BT)
- instr->op = PC_BTLR;
- else
- instr->op = PC_BFLR;
- instr->argCount = 2;
- changed = 1;
- } else if (target->op == PC_BCTR) {
- if (instr->op == PC_BT)
- instr->op = PC_BTCTR;
- else
- instr->op = PC_BFCTR;
- instr->argCount = 2;
- changed = 1;
- } else if (
- block2->nextBlock &&
- block2->nextBlock->firstPCode &&
- block2->nextBlock->firstPCode->op == PC_BLR &&
- label->block->codeOffset == (offset + 8)
- ) {
- if (
- block2->nextBlock->predecessors &&
- block2->nextBlock->predecessors->block == block2 &&
- !block2->nextBlock->predecessors->nextLink
- ) {
- if (instr->op == PC_BT)
- instr->op = PC_BFLR;
- else
- instr->op = PC_BTLR;
- change_num_operands(instr, 2);
- deletepcode(block2->nextBlock->firstPCode);
- changed = deleted = 1;
- }
- } else if (
- block2->nextBlock &&
- block2->nextBlock->firstPCode &&
- block2->nextBlock->firstPCode->op == PC_BCTR &&
- label->block->codeOffset == (offset + 8)
- ) {
- if (
- block2->nextBlock->predecessors &&
- block2->nextBlock->predecessors->block == block2 &&
- !block2->nextBlock->predecessors->nextLink
- ) {
- if (instr->op == PC_BT)
- instr->op = PC_BFCTR;
- else
- instr->op = PC_BTCTR;
- change_num_operands(instr, 2);
- deletepcode(block2->nextBlock->firstPCode);
- changed = deleted = 1;
- }
- }
- }
- continue;
- }
-
- if (
- instr->op == PC_BC &&
- instr->args[3].kind == PCOp_LABEL &&
- !(PCODE_FLAG_SET_T(instr) & (fSideEffects | fLink))
- )
- {
- PCodeBlock *block2 = instr->block;
- label = instr->args[3].data.label.label;
- target = targetinstruction(label);
-
- if (label->block->codeOffset == (offset + 4)) {
- deletepcode(instr);
- changed = deleted = 1;
- } else if (target->op == PC_B) {
- if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[3].data.label.label) {
- instr->args[3].data.label.label = target->args[0].data.label.label;
- changed = 1;
- }
- } else if (copts.opt_bcc_lr_ctr) {
- if (target->op == PC_BLR) {
- instr->op = PC_BCLR;
- instr->argCount = 3;
- changed = 1;
- } else if (target->op == PC_BCTR) {
- instr->op = PC_BCCTR;
- instr->argCount = 3;
- changed = 1;
- } else if (
- block2->nextBlock &&
- block2->nextBlock->firstPCode &&
- block2->nextBlock->firstPCode->op == PC_BLR &&
- label->block->codeOffset == (offset + 8)
- ) {
- SInt32 val = instr->args[0].data.imm.value & 30;
- if (
- block2->nextBlock->predecessors &&
- block2->nextBlock->predecessors->block == block2 &&
- !block2->nextBlock->predecessors->nextLink
- ) {
- if ((val & 30) == 4)
- instr->args[0].data.imm.value = val | 12;
- else if ((val & 30) == 12)
- instr->args[0].data.imm.value = val & 23;
- instr->op = PC_BCLR;
- instr->argCount = 3;
- deletepcode(block2->nextBlock->firstPCode);
- changed = deleted = 1;
- }
- } else if (
- block2->nextBlock &&
- block2->nextBlock->firstPCode &&
- block2->nextBlock->firstPCode->op == PC_BCTR &&
- label->block->codeOffset == (offset + 8)
- ) {
- SInt32 val = instr->args[0].data.imm.value & 30;
- if (
- block2->nextBlock->predecessors &&
- block2->nextBlock->predecessors->block == block2 &&
- !block2->nextBlock->predecessors->nextLink
- ) {
- if ((val & 30) == 4)
- instr->args[0].data.imm.value = val | 12;
- else if ((val & 30) == 12)
- instr->args[0].data.imm.value = val & 23;
- instr->op = PC_BCCTR;
- instr->argCount = 3;
- deletepcode(block2->nextBlock->firstPCode);
- changed = deleted = 1;
- }
- }
- }
- }
- }
-
- if (deleted)
- codesize = pccomputeoffsets();
- } while (changed);
-
- return codesize;
-}
-
-static SInt32 insert_align_nops(Object *func, SInt32 codesize) {
- PCodeBlock *block;
- int changed;
- PCodeBlock *prev;
-
- do {
- changed = 0;
-
- for (block = pcbasicblocks; block; block = block->nextBlock) {
- if (
- (block->flags & fPCBlockFlag6000) == fPCBlockFlag2000 &&
- (block->codeOffset & 7) &&
- block->pcodeCount < 8 &&
- (prev = block->prevBlock) &&
- !(prev->flags & fPCBlockFlag2000)
- )
- {
- if (prev->lastPCode && prev->lastPCode->op == PC_NOP && !(prev->lastPCode->flags & fSideEffects)) {
- deletepcode(prev->lastPCode);
- } else {
- PCode *nop = makepcode(PC_NOP);
- nop->flags &= ~fSideEffects;
- appendpcode(prev, nop);
- }
-
- codesize = pccomputeoffsets();
- changed = 1;
- }
- }
-
- if (changed) {
- pclistblocks(CMangler_GetLinkName(func)->name, "AFTER INSERT ALIGN NOPs");
- if (codesize > 32766) {
- insertlongbranches(32766);
- codesize = pccomputeoffsets();
- }
- }
-
- } while (changed);
-
- return codesize;
-}
-
-SInt32 assemblefunction(Object *func, EntryPoint *entrypoints) {
- void *tbdata;
- GList *gl;
- PCodeBlock *block;
- PCode *instr;
- SInt32 offset2;
- SInt32 codesize;
- SInt32 tbsize;
- SInt32 offset;
- SectionHandle section;
- EntryPoint *ep;
- WeirdOperand wop;
-
- codesize = pccomputeoffsets();
- if (codesize <= 0)
- PPCError_Error(PPCErrorStr190, func->name->name);
-
- if (copts.peephole || copts.optimizationlevel >= 3)
- codesize = optimizefinalbranches(codesize);
-
- if (codesize > 32766) {
- insertlongbranches(32766);
- codesize = pccomputeoffsets();
- }
-
- if (copts.function_align > 4)
- codesize = insert_align_nops(func, codesize);
-
- tbsize = 0;
- if (copts.traceback)
- tbdata = generate_traceback(codesize, CMangler_GetLinkName(func)->name, &tbsize, func);
-
- if (func->section == SECT_DEFAULT)
- func->section = SECT_TEXT;
-
- offset = tbsize;
- section = ObjGen_DeclareCode(func, codesize + tbsize);
- gl = ObjGen_GetSectionGList(section);
-
- codebase = gl->size;
- AppendGListNoData(gl, codesize + tbsize);
-
- if (copts.filesyminfo) {
- ObjGen_SymFunc(func);
- ObjGen_Line(functionbodyoffset, 0);
- ObjGen_DeclareSymInfo();
- }
-
- if (uses_globals && pic_base_reg)
- ObjGen_DeclarePICBase(func, pic_base_pcodelabel->block->codeOffset);
-
- if (entrypoints) {
- for (ep = entrypoints; ep; ep = ep->next) {
- ObjGen_DeclareEntry(ep->object, ep->block->codeOffset);
- }
- }
-
- for (block = pcbasicblocks; block; block = block->nextBlock) {
- for (offset2 = block->codeOffset, instr = block->firstPCode; instr; instr = instr->nextPCode, offset2 += 4) {
- if (copts.filesyminfo && instr->sourceoffset != -1)
- ObjGen_Line(instr->sourceoffset, offset2);
-
- *((UInt32 *) (*gl->data + codebase + offset2)) = assemblepcode(instr, offset2, &wop);
-
- if (wop.type != -1)
- ObjGen_RelocateObj(section, offset2, wop.x2, wop.type);
- }
- }
-
- if (copts.filesyminfo)
- ObjGenMach_SymFuncEnd(func, codesize);
-
- if (copts.traceback)
- memcpy(*gl->data + codebase + codesize, tbdata, offset);
-
- if (copts.traceback)
- return codesize + tbsize;
- else
- return codesize;
-}