| ... | @@ -1142,6 +1142,79 @@ pub const Instruction = union(enum) { | ... | @@ -1142,6 +1142,79 @@ pub const Instruction = union(enum) { |
| 1142 | return stmdb(cond, .sp, true, @bitCast(RegisterList, register_list)); | 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 | test "serialize instructions" { | 1220 | test "serialize instructions" { |
| ... | @@ -1262,6 +1335,20 @@ test "aliases" { | ... | @@ -1262,6 +1335,20 @@ test "aliases" { |
| 1262 | .actual = Instruction.push(.al, .{ .r0, .r2 }), | 1335 | .actual = Instruction.push(.al, .{ .r0, .r2 }), |
| 1263 | .expected = Instruction.stmdb(.al, .sp, true, .{ .r0 = true, .r2 = true }), | 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 | for (testcases) |case| { | 1354 | for (testcases) |case| { |