//This step is only used by the Word/Byte versions void BuildLoadStore_WordAndByte(LoadStoreBuilder b) { //Phase 0 - Choose memory size (word/byte) string originalName = b.name; b.opcode &= ~loadstore_byte_bit; //Case 1: Word b.memorySize = ARMPluginInterfaces.MemorySize.Word; BuildLoadStore_Offset(b); //Case 2: Byte b.name += "B"; b.opcode |= loadstore_byte_bit; b.memorySize = ARMPluginInterfaces.MemorySize.Byte; BuildLoadStore_Offset(b); b.name = originalName; b.opcode &= ~loadstore_byte_bit; }
//This version applies to Word or Byte versions void BuildLoadStore_Offset(LoadStoreBuilder b) { //Phase 1 - Set operand type (register/immediate) //Clear register flag b.opcode &= ~loadstore_register_bit; //Immediate Offset (register flag 0) b.ComputeOffset = ComputeOffsetImmediate; BuildLoadStore_OffsetAddress(b); //Register Offset (register flag 1) b.opcode |= loadstore_register_bit; b.ComputeOffset = ComputeOffsetRegister; BuildLoadStore_OffsetAddress(b); //Clear register flag b.opcode &= ~loadstore_register_bit; }
void BuildLoadStore_OffsetAddress(LoadStoreBuilder b) { //Phase 2 - Set add/subtract behavior (i.e. is offset_address = "address + offset" or "address - offset" //Clear add/subtract flag (U bit) b.opcode &= ~offset_add_bit; //Subtract (U bit = 0) b.ComputeOffsetAddress = ComputeOffsetAddressSubtract; BuildLoadStore_IndexWriteBack(b); //Add (U bit = 1) b.opcode |= offset_add_bit; b.ComputeOffsetAddress = ComputeOffsetAddressAdd; BuildLoadStore_IndexWriteBack(b); //Clear add/subtract flag b.opcode &= ~offset_add_bit; }
//This version applies to Halfword/Signed Halfword/Signed Byte versions void BuildLoadStore_Offset_SignedByte_HalfWord(LoadStoreBuilder b) { //Phase 1 - Set operand type (register/immediate) //Clear register flag b.opcode &= ~loadstore_immediate_bit_hw; //Register Offset (immediate flag 0) b.ComputeOffset = ComputeOffsetRegisterHW; BuildLoadStore_OffsetAddress(b); //Immediate Offset (immediate flag 1) b.opcode |= loadstore_immediate_bit_hw; b.ComputeOffset = ComputeOffsetImmediateHW; BuildLoadStore_OffsetAddress(b); //Clear register flag b.opcode &= ~loadstore_immediate_bit_hw; }
void BuildLoadStore_IndexWriteBack(LoadStoreBuilder b) { //Phase 3 - Set indexing (pre or post) and writeback behavior //Even though these are theoretically independent options, there is a special case //So we handle them all here. //Clear relevant flags: b.opcode &= ~(loadstore_preindex_bit | writeback_bit); //Case 1: Post-indexing (index_bit = 0) with writeback (by default) and writeback_bit = 0 //Note that post-indexing is supposed to always have writeback, so the correct //protocol is for W = 0 when index_bit = 0. b.ComputeFinalAddress = ComputeAddressPostIndex; b.WritebackAddress = WritebackAddressEnabled; FinishBuildingLoadStoreOp(b); b.opcode &= ~(loadstore_preindex_bit | writeback_bit); //Case 2: Post-indexing (index_bit = 0) with writeback (by default) and writeback_bit = 1 //This actually corresponds to a special type of instruction with a T suffix (e.g. STRT) //cf. ARMv7 A8.8.92 //For now, we ignore it. //TODO stop ignoring it. //Case 3: Pre-indexing (index_bit = 1) with no writeback (writeback_bit = 0) b.opcode |= loadstore_preindex_bit; b.ComputeFinalAddress = ComputeAddressPreIndex; b.WritebackAddress = WritebackAddressDisabled; FinishBuildingLoadStoreOp(b); b.opcode &= ~(loadstore_preindex_bit | writeback_bit); //Case 3: Pre-indexing (index_bit = 1) with writeback (writeback_bit = 1) b.opcode |= loadstore_preindex_bit | writeback_bit; b.ComputeFinalAddress = ComputeAddressPreIndex; b.WritebackAddress = WritebackAddressEnabled; FinishBuildingLoadStoreOp(b); //Clear relevant flags: b.opcode &= ~(loadstore_preindex_bit | writeback_bit); }
internal void RegisterARMLoadStoreOps() { uint base_opcode; uint wildcard_mask; //The values of bits 20-27 vary between branches. The bit B (bit 4) in the specification is irrelevant here. LoadStoreBuilder b = new LoadStoreBuilder(); //Create variants of STR and STRB base_opcode = 0x04000000; wildcard_mask = 0xf00fffff; //The values of bits 20-27 vary between branches. The bit B (bit 4) in the specification is irrelevant here. b.name = "STR"; b.opcode = base_opcode; b.wildcard_mask = wildcard_mask; b.LoadStoreMemory = StoreMemory; BuildLoadStore_WordAndByte(b); //Create variants of LDR and LDRB base_opcode = 0x04100000; wildcard_mask = 0xf00fffff; b.name = "LDR"; b.opcode = base_opcode; b.wildcard_mask = wildcard_mask; b.LoadStoreMemory = LoadMemory; BuildLoadStore_WordAndByte(b); //Create variants of STRH base_opcode = 0x000000b0; wildcard_mask = 0xf00fff0f; b.name = "STRH"; b.opcode = base_opcode; b.wildcard_mask = wildcard_mask; b.LoadStoreMemory = StoreMemory; b.memorySize = ARMPluginInterfaces.MemorySize.HalfWord; BuildLoadStore_Offset_SignedByte_HalfWord(b); //Create variants of LDRH base_opcode = 0x001000b0; wildcard_mask = 0xf00fff0f; b.name = "LDRH"; b.opcode = base_opcode; b.wildcard_mask = wildcard_mask; b.LoadStoreMemory = LoadMemory; b.memorySize = ARMPluginInterfaces.MemorySize.HalfWord; BuildLoadStore_Offset_SignedByte_HalfWord(b); //Create variants of LDRSB (signed byte) base_opcode = 0x001000d0; wildcard_mask = 0xf00fff0f; b.name = "LDRSB"; b.opcode = base_opcode; b.wildcard_mask = wildcard_mask; b.LoadStoreMemory = LoadMemorySignedByte; b.memorySize = ARMPluginInterfaces.MemorySize.Byte; BuildLoadStore_Offset_SignedByte_HalfWord(b); //Create variants of LDRSH (signed halfword) base_opcode = 0x001000f0; wildcard_mask = 0xf00fff0f; b.name = "LDRSB"; b.opcode = base_opcode; b.wildcard_mask = wildcard_mask; b.LoadStoreMemory = LoadMemorySignedHalfword; b.memorySize = ARMPluginInterfaces.MemorySize.HalfWord; BuildLoadStore_Offset_SignedByte_HalfWord(b); //LDRD and STRD are load/store "dual" instructions which load or store two //adjacent words to two registers. //LDRD is v5TE only //RegisterOpcode(0x000000d0, 0xf1afff0f, null, "LDRD"); //LDRD (Register) //RegisterOpcode(0x004000d0, 0xf1afff0f, null, "LDRD"); //LDRD (immediate) //STRD is v5 and up only //RegisterOpcode(0x000000f0, 0xf1afff0f, null, "STRD"); //STRD (Register) //RegisterOpcode(0x004000f0, 0xf1afff0f, null, "STRD"); //STRD (immediate) }
internal void FinishBuildingLoadStoreOp(LoadStoreBuilder b) { InstructionFunc handler = GenerateLoadStoreInstruction(b.ComputeOffset, b.ComputeOffsetAddress, b.ComputeFinalAddress, b.WritebackAddress, b.memorySize, b.LoadStoreMemory); RegisterOpcode(b.opcode, b.wildcard_mask, handler, b.name); }