-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathlib.rs
122 lines (104 loc) · 2.66 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
pub use ppcasm_macro::ppcasm;
use std::io;
use byteorder::{BigEndian, WriteBytesExt};
pub use generic_array;
pub fn upper_bits(n: u32) -> i32
{
if n & 0x8000 == 0x8000 {
((n >> 16) as i32) + 1
} else {
(n >> 16) as i32
}
}
pub fn lower_bits(n: u32) -> i32
{
(n & 0xFFFF) as i32
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AsmBlock<A, L>
{
addr: u32,
instrs: A,
labels: L,
}
impl<A, L> AsmBlock<A, L>
where A: AsRef<[u32]>
{
pub fn new(addr: u32, instrs: A, labels: L) -> AsmBlock<A, L>
{
AsmBlock { addr, instrs, labels }
}
pub fn write_encoded<W: io::Write>(&self, w: &mut W) -> io::Result<()>
{
for instr in self.instrs.as_ref().iter() {
w.write_u32::<BigEndian>(*instr)?
}
Ok(())
}
pub fn encoded_bytes(&self) -> Vec<u8>
{
let mut v = Vec::with_capacity(self.instrs.as_ref().len() * 4);
self.write_encoded(&mut v).unwrap();
v
}
pub fn addr(&self) -> u32
{
self.addr
}
pub fn labels(&self) -> &L
{
&self.labels
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AsmInstrPart(u8, u32);
impl AsmInstrPart
{
pub fn new<T: Into<i64>>(bit_len: u8, data: T) -> AsmInstrPart
{
if bit_len > 32 {
panic!("AsmInstrPart bit_len may not exceed 32 (max 32 bits per instruction)")
}
let data = data.into();
let data = if data >= 0 {
if (1 << bit_len) - 1 < data {
panic!("AsmInstrPart value {:x} is longer than {} bits", data, bit_len)
}
data as u32
} else {
// NOTE: (bit_len - 1) because the top bit MUST be negative in 2s complement
if -1 << (bit_len - 1) > data {
panic!("AsmInstrPart value {:x} is longer than {} bits", data, bit_len)
}
if bit_len == 32 {
data as u32
} else {
// Zero out the upper bits
data as u32 & ((1 << bit_len) - 1)
}
};
AsmInstrPart(bit_len, data)
}
pub fn bit_len(&self) -> u8
{
self.0
}
fn shiftable_bit_len(&self) -> u8
{
if self.0 == 32 { 0 } else { self.0 }
}
pub fn encoding(&self) -> u32
{
self.1
}
pub fn assemble(parts: &[AsmInstrPart]) -> u32
{
let total_bits: u8 = parts.iter()
.map(|p| p.bit_len())
.sum();
if total_bits != 32 {
panic!("Failed to encode instruction, too may bits")
}
parts.iter().fold(0, |s, p| (s << p.shiftable_bit_len()) | p.encoding())
}
}