|
| 1 | +use super::{InlineAsmArch, InlineAsmType}; |
| 2 | +use rustc_macros::HashStable_Generic; |
| 3 | +use std::fmt; |
| 4 | + |
| 5 | +def_reg_class! { |
| 6 | + Avr AvrInlineAsmRegClass { |
| 7 | + reg, |
| 8 | + reg_upper, |
| 9 | + reg_pair, |
| 10 | + reg_iw, |
| 11 | + reg_ptr, |
| 12 | + } |
| 13 | +} |
| 14 | + |
| 15 | +impl AvrInlineAsmRegClass { |
| 16 | + pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] { |
| 17 | + match self { |
| 18 | + Self::reg_pair | Self::reg_iw | Self::reg_ptr => &['h', 'l'], |
| 19 | + _ => &[], |
| 20 | + } |
| 21 | + } |
| 22 | + |
| 23 | + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> { |
| 24 | + None |
| 25 | + } |
| 26 | + |
| 27 | + pub fn suggest_modifier( |
| 28 | + self, |
| 29 | + _arch: InlineAsmArch, |
| 30 | + _ty: InlineAsmType, |
| 31 | + ) -> Option<(char, &'static str)> { |
| 32 | + None |
| 33 | + } |
| 34 | + |
| 35 | + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { |
| 36 | + None |
| 37 | + } |
| 38 | + |
| 39 | + pub fn supported_types( |
| 40 | + self, |
| 41 | + _arch: InlineAsmArch, |
| 42 | + ) -> &'static [(InlineAsmType, Option<&'static str>)] { |
| 43 | + match self { |
| 44 | + Self::reg => types! { _: I8; }, |
| 45 | + Self::reg_upper => types! { _: I8; }, |
| 46 | + Self::reg_pair => types! { _: I16; }, |
| 47 | + Self::reg_iw => types! { _: I16; }, |
| 48 | + Self::reg_ptr => types! { _: I16; }, |
| 49 | + } |
| 50 | + } |
| 51 | +} |
| 52 | + |
| 53 | +def_regs! { |
| 54 | + Avr AvrInlineAsmReg AvrInlineAsmRegClass { |
| 55 | + r2: reg = ["r2"], |
| 56 | + r3: reg = ["r3"], |
| 57 | + r4: reg = ["r4"], |
| 58 | + r5: reg = ["r5"], |
| 59 | + r6: reg = ["r6"], |
| 60 | + r7: reg = ["r7"], |
| 61 | + r8: reg = ["r8"], |
| 62 | + r9: reg = ["r9"], |
| 63 | + r10: reg = ["r10"], |
| 64 | + r11: reg = ["r11"], |
| 65 | + r12: reg = ["r12"], |
| 66 | + r13: reg = ["r13"], |
| 67 | + r14: reg = ["r14"], |
| 68 | + r15: reg = ["r15"], |
| 69 | + r16: reg, reg_upper = ["r16"], |
| 70 | + r17: reg, reg_upper = ["r17"], |
| 71 | + r18: reg, reg_upper = ["r18"], |
| 72 | + r19: reg, reg_upper = ["r19"], |
| 73 | + r20: reg, reg_upper = ["r20"], |
| 74 | + r21: reg, reg_upper = ["r21"], |
| 75 | + r22: reg, reg_upper = ["r22"], |
| 76 | + r23: reg, reg_upper = ["r23"], |
| 77 | + r24: reg, reg_upper = ["r24"], |
| 78 | + r25: reg, reg_upper = ["r25"], |
| 79 | + r26: reg, reg_upper = ["r26", "XL"], |
| 80 | + r27: reg, reg_upper = ["r27", "XH"], |
| 81 | + r30: reg, reg_upper = ["r30", "ZL"], |
| 82 | + r31: reg, reg_upper = ["r31", "ZH"], |
| 83 | + |
| 84 | + r3r2: reg_pair = ["r3r2"], |
| 85 | + r5r4: reg_pair = ["r5r4"], |
| 86 | + r7r6: reg_pair = ["r7r6"], |
| 87 | + r9r8: reg_pair = ["r9r8"], |
| 88 | + r11r10: reg_pair = ["r11r10"], |
| 89 | + r13r12: reg_pair = ["r13r12"], |
| 90 | + r15r14: reg_pair = ["r15r14"], |
| 91 | + r17r16: reg_pair = ["r17r16"], |
| 92 | + r19r18: reg_pair = ["r19r18"], |
| 93 | + r21r20: reg_pair = ["r21r20"], |
| 94 | + r23r22: reg_pair = ["r23r22"], |
| 95 | + |
| 96 | + r25r24: reg_iw, reg_pair = ["r25r24"], |
| 97 | + |
| 98 | + X: reg_ptr, reg_iw, reg_pair = ["r27r26", "X"], |
| 99 | + Z: reg_ptr, reg_iw, reg_pair = ["r31r30", "Z"], |
| 100 | + |
| 101 | + #error = ["Y", "YL", "YH"] => |
| 102 | + "the frame pointer cannot be used as an operand for inline asm", |
| 103 | + #error = ["SP", "SPL", "SPH"] => |
| 104 | + "the stack pointer cannot be used as an operand for inline asm", |
| 105 | + #error = ["r0", "r1", "r1r0"] => |
| 106 | + "r0 and r1 are not available due to an issue in LLVM", |
| 107 | + } |
| 108 | +} |
| 109 | + |
| 110 | +macro_rules! emit_pairs { |
| 111 | + ( |
| 112 | + $self:ident $modifier:ident, |
| 113 | + $($pair:ident $name:literal $hi:literal $lo:literal,)* |
| 114 | + ) => { |
| 115 | + match ($self, $modifier) { |
| 116 | + $( |
| 117 | + (AvrInlineAsmReg::$pair, Some('h')) => $hi, |
| 118 | + (AvrInlineAsmReg::$pair, Some('l')) => $lo, |
| 119 | + (AvrInlineAsmReg::$pair, _) => $name, |
| 120 | + )* |
| 121 | + _ => $self.name(), |
| 122 | + } |
| 123 | + }; |
| 124 | +} |
| 125 | + |
| 126 | +impl AvrInlineAsmReg { |
| 127 | + pub fn emit( |
| 128 | + self, |
| 129 | + out: &mut dyn fmt::Write, |
| 130 | + _arch: InlineAsmArch, |
| 131 | + modifier: Option<char>, |
| 132 | + ) -> fmt::Result { |
| 133 | + let name = emit_pairs! { |
| 134 | + self modifier, |
| 135 | + Z "Z" "ZH" "ZL", |
| 136 | + X "X" "XH" "XL", |
| 137 | + r25r24 "r25:r24" "r25" "r24", |
| 138 | + r23r22 "r23:r22" "r23" "r22", |
| 139 | + r21r20 "r21:r20" "r21" "r20", |
| 140 | + r19r18 "r19:r18" "r19" "r18", |
| 141 | + r17r16 "r17:r16" "r17" "r16", |
| 142 | + r15r14 "r15:r14" "r15" "r14", |
| 143 | + r13r12 "r13:r12" "r13" "r12", |
| 144 | + r11r10 "r11:r10" "r11" "r10", |
| 145 | + r9r8 "r9:r8" "r9" "r8", |
| 146 | + r7r6 "r7:r6" "r7" "r6", |
| 147 | + r5r4 "r5:r4" "r5" "r4", |
| 148 | + r3r2 "r3:r2" "r3" "r2", |
| 149 | + }; |
| 150 | + out.write_str(name) |
| 151 | + } |
| 152 | + |
| 153 | + pub fn overlapping_regs(self, mut cb: impl FnMut(AvrInlineAsmReg)) { |
| 154 | + cb(self); |
| 155 | + |
| 156 | + macro_rules! reg_conflicts { |
| 157 | + ( |
| 158 | + $( |
| 159 | + $pair:ident : $hi:ident $lo:ident, |
| 160 | + )* |
| 161 | + ) => { |
| 162 | + match self { |
| 163 | + $( |
| 164 | + Self::$pair => { |
| 165 | + cb(Self::$hi); |
| 166 | + cb(Self::$lo); |
| 167 | + } |
| 168 | + Self::$hi => { |
| 169 | + cb(Self::$pair); |
| 170 | + } |
| 171 | + Self::$lo => { |
| 172 | + cb(Self::$pair); |
| 173 | + } |
| 174 | + )* |
| 175 | + } |
| 176 | + }; |
| 177 | + } |
| 178 | + |
| 179 | + reg_conflicts! { |
| 180 | + Z : r31 r30, |
| 181 | + X : r27 r26, |
| 182 | + r25r24 : r25 r24, |
| 183 | + r23r22 : r23 r22, |
| 184 | + r21r20 : r21 r20, |
| 185 | + r19r18 : r19 r18, |
| 186 | + r17r16 : r17 r16, |
| 187 | + r15r14 : r15 r14, |
| 188 | + r13r12 : r13 r12, |
| 189 | + r11r10 : r11 r10, |
| 190 | + r9r8 : r9 r8, |
| 191 | + r7r6 : r7 r6, |
| 192 | + r5r4 : r5 r4, |
| 193 | + r3r2 : r3 r2, |
| 194 | + } |
| 195 | + } |
| 196 | +} |
0 commit comments