| ... | ... | @@ -1142,6 +1142,79 @@ pub const Instruction = union(enum) { |
| 1142 | 1142 | return stmdb(cond, .sp, true, @bitCast(RegisterList, register_list)); |
| 1143 | 1143 | } |
| 1144 | 1144 | } |
| 1145 | |
| 1146 | pub const ShiftAmount = union(enum) { |
| 1147 | immediate: u5, |
| 1148 | register: Register, |
| 1149 | |
| 1150 | pub fn imm(immediate: u5) ShiftAmount { |
| 1151 | return .{ |
| 1152 | .immediate = immediate, |
| 1153 | }; |
| 1154 | } |
| 1155 | |
| 1156 | pub fn reg(register: Register) ShiftAmount { |
| 1157 | return .{ |
| 1158 | .register = register, |
| 1159 | }; |
| 1160 | } |
| 1161 | }; |
| 1162 | |
| 1163 | pub fn lsl(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction { |
| 1164 | return switch (shift) { |
| 1165 | .immediate => |imm| mov(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .logical_left))), |
| 1166 | .register => |reg| mov(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .logical_left))), |
| 1167 | }; |
| 1168 | } |
| 1169 | |
| 1170 | pub fn lsr(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction { |
| 1171 | return switch (shift) { |
| 1172 | .immediate => |imm| mov(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .logical_right))), |
| 1173 | .register => |reg| mov(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .logical_right))), |
| 1174 | }; |
| 1175 | } |
| 1176 | |
| 1177 | pub fn asr(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction { |
| 1178 | return switch (shift) { |
| 1179 | .immediate => |imm| mov(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .arithmetic_right))), |
| 1180 | .register => |reg| mov(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .arithmetic_right))), |
| 1181 | }; |
| 1182 | } |
| 1183 | |
| 1184 | pub fn ror(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction { |
| 1185 | return switch (shift) { |
| 1186 | .immediate => |imm| mov(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .rotate_right))), |
| 1187 | .register => |reg| mov(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .rotate_right))), |
| 1188 | }; |
| 1189 | } |
| 1190 | |
| 1191 | pub fn lsls(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction { |
| 1192 | return switch (shift) { |
| 1193 | .immediate => |imm| movs(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .logical_left))), |
| 1194 | .register => |reg| movs(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .logical_left))), |
| 1195 | }; |
| 1196 | } |
| 1197 | |
| 1198 | pub fn lsrs(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction { |
| 1199 | return switch (shift) { |
| 1200 | .immediate => |imm| movs(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .logical_right))), |
| 1201 | .register => |reg| movs(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .logical_right))), |
| 1202 | }; |
| 1203 | } |
| 1204 | |
| 1205 | pub fn asrs(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction { |
| 1206 | return switch (shift) { |
| 1207 | .immediate => |imm| movs(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .arithmetic_right))), |
| 1208 | .register => |reg| movs(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .arithmetic_right))), |
| 1209 | }; |
| 1210 | } |
| 1211 | |
| 1212 | pub fn rors(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction { |
| 1213 | return switch (shift) { |
| 1214 | .immediate => |imm| movs(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .rotate_right))), |
| 1215 | .register => |reg| movs(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .rotate_right))), |
| 1216 | }; |
| 1217 | } |
| 1145 | 1218 | }; |
| 1146 | 1219 | |
| 1147 | 1220 | test "serialize instructions" { |
| ... | ... | @@ -1262,6 +1335,20 @@ test "aliases" { |
| 1262 | 1335 | .actual = Instruction.push(.al, .{ .r0, .r2 }), |
| 1263 | 1336 | .expected = Instruction.stmdb(.al, .sp, true, .{ .r0 = true, .r2 = true }), |
| 1264 | 1337 | }, |
| 1338 | .{ // lsl r4, r5, #5 |
| 1339 | .actual = Instruction.lsl(.al, .r4, .r5, Instruction.ShiftAmount.imm(5)), |
| 1340 | .expected = Instruction.mov(.al, .r4, Instruction.Operand.reg( |
| 1341 | .r5, |
| 1342 | Instruction.Operand.Shift.imm(5, .logical_left), |
| 1343 | )), |
| 1344 | }, |
| 1345 | .{ // asrs r1, r1, r3 |
| 1346 | .actual = Instruction.asrs(.al, .r1, .r1, Instruction.ShiftAmount.reg(.r3)), |
| 1347 | .expected = Instruction.movs(.al, .r1, Instruction.Operand.reg( |
| 1348 | .r1, |
| 1349 | Instruction.Operand.Shift.reg(.r3, .arithmetic_right), |
| 1350 | )), |
| 1351 | }, |
| 1265 | 1352 | }; |
| 1266 | 1353 | |
| 1267 | 1354 | for (testcases) |case| { |