Support b/bl instructions

This commit is contained in:
Spotlight 2022-01-01 17:37:27 -06:00
parent 4eb530b71e
commit c8559722ea
No known key found for this signature in database
GPG Key ID: 874AA355B3209BDC
4 changed files with 81 additions and 10 deletions

View File

@ -54,7 +54,7 @@ func generateTag(tag Tag, tagContents []byte) []byte {
byte(tag),
}
// Tag length
contents = append(contents, toLength(len(tagContents))...)
contents = append(contents, fourByte(uint32(len(tagContents)))...)
// Tag contents
contents = append(contents, tagContents...)
@ -120,9 +120,9 @@ func generateOperaCertStore() {
file.Write(append(header, caCertTag...))
}
// toLength returns 4 bytes, suitable for the given length.
func toLength(value int) []byte {
// fourByte returns 4 bytes, suitable for the given length.
func fourByte(value uint32) []byte {
holder := make([]byte, 4)
binary.BigEndian.PutUint32(holder, uint32(value))
binary.BigEndian.PutUint32(holder, value)
return holder
}

View File

@ -36,7 +36,7 @@ func LoadCustomCA() PatchSet {
LWZ(R3, 0xac, R28),
LWZ(R5, 0xc4, R28),
// SSLSetRootCA(ssl_fd, ca_cert, cert_index)
Instruction{0x48, 0x01, 0x59, 0x49},
BL(0x800acae4, 0x800c242c),
// Check if successful
CMPWI(R3, 0),
@ -46,7 +46,7 @@ func LoadCustomCA() PatchSet {
// Return error -1004 if failed
LI(R3, 0xfc14),
// b FUNCTION_PROLOG
Instruction{0x48, 0x00, 0x00, 0xbc},
B(0x800acaf4, 0x800acbb0),
// ----
@ -56,7 +56,7 @@ func LoadCustomCA() PatchSet {
LWZ(R3, 0xac, R28),
LWZ(R4, 0xd8, R28),
// SSLSetBuiltinRootCA(ssl_fd, cert_index)
Instruction{0x48, 0x01, 0x5a, 0x75},
BL(0x800acb00, 0x800c2574),
// Check if successful
CMPWI(R3, 0),
@ -66,7 +66,7 @@ func LoadCustomCA() PatchSet {
// Return error -1004 if failed
LI(R3, 0xfc14),
// b FUNCTION_PROLOG
Instruction{0x48, 0x00, 0x00, 0xa0},
B(0x800acb10, 0x800acbb0),
}.toBytes(),
After: Instructions{
// Our certificate is present at 0x802e97b8.
@ -84,7 +84,7 @@ func LoadCustomCA() PatchSet {
LWZ(R3, 0xac, R28),
// SSLSetRootCA(ssl_fd, ca_cert, cert_index)
Instruction{0x48, 0x01, 0x59, 0x49},
BL(0x800acae4, 0x800c242c),
// Check for errors
CMPWI(R3, 0),
@ -94,7 +94,7 @@ func LoadCustomCA() PatchSet {
// Return error -1004 if failed
LI(R3, 0xfc14),
// b FUNCTION_PROLOG
Instruction{0x48, 0x00, 0x00, 0xbc},
B(0x800acaf4, 0x800acbb0),
// NOP the rest in order to allow execution to continue.
NOP(), NOP(), NOP(), NOP(), NOP(), NOP(), NOP(),

View File

@ -1,5 +1,15 @@
package main
// uint24 returns
func uint24(num uint32) [3]byte {
if num > 0x00FFFFFF {
panic("invalid uint24 passed")
}
result := fourByte(num)
return [3]byte{result[1], result[2], result[3]}
}
// Instruction represents a 4-byte PowerPC instruction.
type Instruction [4]byte
@ -102,3 +112,28 @@ func MFSPR() Instruction {
func STWU(rS Register, rA Register, offset uint16) Instruction {
return EncodeInstrDForm(37, rS, rA, offset)
}
// calcDestination determines the proper offset from a given
// calling address and target address.
func calcDestination(from uint, target uint) [3]byte {
// TODO(spotlightishere): Handle negative offsets properly
offset := target - from
// Sign-extend by two bytes
calc := uint32(offset >> 2)
return uint24(calc)
}
// BL represents the bl PowerPC instruction.
// It calculates the offset from the given current address and the given
// target address, saving the current address in the link register. It then branches.
func BL(current uint, target uint) Instruction {
return EncodeInstrIForm(18, calcDestination(current, target), false, true)
}
// B represents the b PowerPC instruction.
// It calculates the offset from the given current address
// and the given target address, and then branches.
func B(current uint, target uint) Instruction {
return EncodeInstrIForm(18, calcDestination(current, target), false, false)
}

View File

@ -116,6 +116,42 @@ func EncodeInstrDForm(opcode byte, rT Register, rA Register, value uint16) Instr
return Instruction{firstInstr, secondInstr, valByte[0], valByte[1]}
}
// EncodeInstrIForm handles encoding a given opcode, LI, AA and LK.
// I-form assumes:
// - 6 bits for the opcode
// - 24 bits for LI
// - 1 bit for absolute (AA)
// - 1 bit for should store in link register (LK)
func EncodeInstrIForm(opcode byte, LI [3]byte, AA bool, LK bool) Instruction {
opBits := getBits(opcode)
liOne := getBits(LI[0])
liTwo := getBits(LI[1])
liThree := getBits(LI[2])
instr := [4]Bits{
{
// We need the upper six bits for our opcode.
opBits[2], opBits[3], opBits[4], opBits[5], opBits[6], opBits[7],
// Otherwise, copy LI as-is.
liOne[0], liOne[1],
},
{
liOne[2], liOne[3], liOne[4], liOne[5], liOne[6], liOne[7], liTwo[0], liTwo[1],
},
{
liTwo[2], liTwo[3], liTwo[4], liTwo[5], liTwo[6], liTwo[7], liThree[0], liThree[1],
},
{
liThree[2], liThree[3], liThree[4], liThree[5], liThree[6], liThree[7],
// Copy AA and LK as-is.
AA,
LK,
},
}
return Instruction{instr[0].getByte(), instr[1].getByte(), instr[2].getByte(), instr[3].getByte()}
}
// twoByte converts a uint16 to two big-endian bytes.
func twoByte(passed uint16) [2]byte {
result := make([]byte, 2)