| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include "native_client/src/trusted/validator_arm/baseline_classes.h" | 7 #include "native_client/src/trusted/validator_arm/baseline_classes.h" |
| 8 | 8 |
| 9 #include <assert.h> | 9 #include <assert.h> |
| 10 #include <string.h> | 10 #include <string.h> |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 // Note: We would restrict out PC as well for Rd in NaCl, but no need | 206 // Note: We would restrict out PC as well for Rd in NaCl, but no need |
| 207 // since the ARM restriction doesn't allow it anyway. | 207 // since the ARM restriction doesn't allow it anyway. |
| 208 return MAY_BE_SAFE; | 208 return MAY_BE_SAFE; |
| 209 } | 209 } |
| 210 | 210 |
| 211 RegisterList Binary4RegisterDualResult::defs(const Instruction i) const { | 211 RegisterList Binary4RegisterDualResult::defs(const Instruction i) const { |
| 212 return RegisterList(d_hi.reg(i)).Add(d_lo.reg(i)). | 212 return RegisterList(d_hi.reg(i)).Add(d_lo.reg(i)). |
| 213 Add(conditions.conds_if_updated(i)); | 213 Add(conditions.conds_if_updated(i)); |
| 214 } | 214 } |
| 215 | 215 |
| 216 // LoadStore2RegisterImmediateOp | 216 // LoadStore2RegisterImm8Op |
| 217 SafetyLevel LoadStore2RegisterImmediateOp::safety(const Instruction i) const { | 217 SafetyLevel LoadStore2RegisterImm8Op::safety(const Instruction i) const { |
| 218 // Arm restrictions for this instruction. | 218 // Arm restrictions for this instruction. |
| 219 if (t.reg(i).Equals(kRegisterPc)) { | 219 if (t.reg(i).Equals(kRegisterPc)) { |
| 220 return UNPREDICTABLE; | 220 return UNPREDICTABLE; |
| 221 } | 221 } |
| 222 | 222 |
| 223 if (HasWriteBack(i) && | 223 if (HasWriteBack(i) && |
| 224 (n.reg(i).Equals(kRegisterPc) || n.reg(i).Equals(t.reg(i)))) { | 224 (n.reg(i).Equals(kRegisterPc) || |
| 225 // NOTE: The manual states that that it is also unpredictable |
| 226 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 227 // may not check for this. For the moment, we are changing |
| 228 // the code to ignore this case for stores. |
| 229 // TODO(karl): Should we not allow this? |
| 230 (is_load_ && n.reg(i).Equals(t.reg(i))))) { |
| 225 return UNPREDICTABLE; | 231 return UNPREDICTABLE; |
| 226 } | 232 } |
| 227 | 233 |
| 228 // Don't allow modification of PC (NaCl constraint). | 234 // Don't allow modification of PC (NaCl constraint). |
| 229 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; | 235 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 230 | 236 |
| 231 return MAY_BE_SAFE; | 237 return MAY_BE_SAFE; |
| 232 } | 238 } |
| 233 | 239 |
| 234 RegisterList LoadStore2RegisterImmediateOp::immediate_addressing_defs( | 240 RegisterList LoadStore2RegisterImm8Op::immediate_addressing_defs( |
| 235 const Instruction i) const { | 241 const Instruction i) const { |
| 236 return RegisterList(HasWriteBack(i) ? n.reg(i) : kRegisterNone); | 242 return RegisterList(HasWriteBack(i) ? n.reg(i) : kRegisterNone); |
| 237 } | 243 } |
| 238 | 244 |
| 239 Register LoadStore2RegisterImmediateOp::base_address_register( | 245 Register LoadStore2RegisterImm8Op::base_address_register( |
| 240 const Instruction i) const { | 246 const Instruction i) const { |
| 241 return n.reg(i); | 247 return n.reg(i); |
| 242 } | 248 } |
| 243 | 249 |
| 244 // Load2RegisterImmediateOp | 250 // Load2RegisterImm8Op |
| 245 RegisterList Load2RegisterImmediateOp::defs(Instruction i) const { | 251 RegisterList Load2RegisterImm8Op::defs(Instruction i) const { |
| 246 return immediate_addressing_defs(i).Add(t.reg(i)); | 252 return immediate_addressing_defs(i).Add(t.reg(i)); |
| 247 } | 253 } |
| 248 | 254 |
| 249 bool Load2RegisterImmediateOp::offset_is_immediate(Instruction i) const { | 255 bool Load2RegisterImm8Op::offset_is_immediate(Instruction i) const { |
| 250 UNREFERENCED_PARAMETER(i); | 256 UNREFERENCED_PARAMETER(i); |
| 251 return true; | 257 return true; |
| 252 } | 258 } |
| 253 | 259 |
| 254 // Store2RegisterImmediateOp | 260 // Store2RegisterImm8Op |
| 255 RegisterList Store2RegisterImmediateOp::defs(Instruction i) const { | 261 RegisterList Store2RegisterImm8Op::defs(Instruction i) const { |
| 256 return immediate_addressing_defs(i); | 262 return immediate_addressing_defs(i); |
| 257 } | 263 } |
| 258 | 264 |
| 259 // LoadStore2RegisterImmediateDoubleOp | 265 // LoadStore2RegisterImm8DoubleOp |
| 260 SafetyLevel LoadStore2RegisterImmediateDoubleOp:: | 266 SafetyLevel LoadStore2RegisterImm8DoubleOp:: |
| 261 safety(const Instruction i) const { | 267 safety(const Instruction i) const { |
| 262 // Arm restrictions for this instruction, based on double width. | 268 // Arm restrictions for this instruction, based on double width. |
| 263 if (!t.IsEven(i)) { | 269 if (!t.IsEven(i)) { |
| 264 return UNDEFINED; | 270 return UNDEFINED; |
| 265 } | 271 } |
| 266 | 272 |
| 267 if (t2.reg(i).Equals(kRegisterPc)) { | 273 if (t2.reg(i).Equals(kRegisterPc)) { |
| 268 return UNPREDICTABLE; | 274 return UNPREDICTABLE; |
| 269 } | 275 } |
| 270 | 276 |
| 271 if (HasWriteBack(i) && n.reg(i).Equals(t2.reg(i))) { | 277 // NOTE: The manual states that that it is also unpredictable |
| 278 // when HasWriteBack(i) and Rn=Rt2. However, the compilers |
| 279 // may not check for this. For the moment, we are changing |
| 280 // the code to ignore this case for stores. |
| 281 // TODO(karl): Should we not allow this? |
| 282 if (is_load_ && HasWriteBack(i) && n.reg(i).Equals(t2.reg(i))) { |
| 272 return UNPREDICTABLE; | 283 return UNPREDICTABLE; |
| 273 } | 284 } |
| 274 | 285 |
| 275 // Now apply non-double width restrictions for this instruction. | 286 // Now apply non-double width restrictions for this instruction. |
| 276 return LoadStore2RegisterImmediateOp::safety(i); | 287 return LoadStore2RegisterImm8Op::safety(i); |
| 277 } | 288 } |
| 278 | 289 |
| 279 // Load2RegisterImmediateDoubleOp | 290 // Load2RegisterImm8DoubleOp |
| 280 RegisterList Load2RegisterImmediateDoubleOp::defs(Instruction i) const { | 291 RegisterList Load2RegisterImm8DoubleOp::defs(Instruction i) const { |
| 281 return immediate_addressing_defs(i).Add(t.reg(i)).Add(t2.reg(i)); | 292 return immediate_addressing_defs(i).Add(t.reg(i)).Add(t2.reg(i)); |
| 282 } | 293 } |
| 283 | 294 |
| 284 bool Load2RegisterImmediateDoubleOp::offset_is_immediate(Instruction i) const { | 295 bool Load2RegisterImm8DoubleOp::offset_is_immediate(Instruction i) const { |
| 285 UNREFERENCED_PARAMETER(i); | 296 UNREFERENCED_PARAMETER(i); |
| 286 return true; | 297 return true; |
| 287 } | 298 } |
| 288 | 299 |
| 289 // Store2RegisterImmediateDoubleOp | 300 // Store2RegisterImm8DoubleOp |
| 290 RegisterList Store2RegisterImmediateDoubleOp::defs(Instruction i) const { | 301 RegisterList Store2RegisterImm8DoubleOp::defs(Instruction i) const { |
| 302 return immediate_addressing_defs(i); |
| 303 } |
| 304 |
| 305 // LoadStore2RegisterImm12Op |
| 306 SafetyLevel LoadStore2RegisterImm12Op::safety(const Instruction i) const { |
| 307 // Arm restrictions for this instruction. |
| 308 if (HasWriteBack(i) && |
| 309 (n.reg(i).Equals(kRegisterPc) || |
| 310 // NOTE: The manual states that that it is also unpredictable |
| 311 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 312 // may not check for this. For the moment, we are changing |
| 313 // the code to ignore this case for stores. |
| 314 // TODO(karl): Should we not allow this? |
| 315 (is_load_ && n.reg(i).Equals(t.reg(i))))) { |
| 316 return UNPREDICTABLE; |
| 317 } |
| 318 |
| 319 // Don't allow modification of PC (NaCl constraint). |
| 320 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 321 |
| 322 // NaCl special restriction to make all load/store immediates behave |
| 323 // the same. |
| 324 if (t.reg(i).Equals(kRegisterPc)) { |
| 325 return FORBIDDEN_OPERANDS; |
| 326 } |
| 327 |
| 328 return MAY_BE_SAFE; |
| 329 } |
| 330 |
| 331 RegisterList LoadStore2RegisterImm12Op::immediate_addressing_defs( |
| 332 const Instruction i) const { |
| 333 return RegisterList(HasWriteBack(i) ? n.reg(i) : kRegisterNone); |
| 334 } |
| 335 |
| 336 Register LoadStore2RegisterImm12Op::base_address_register( |
| 337 const Instruction i) const { |
| 338 return n.reg(i); |
| 339 } |
| 340 |
| 341 // Load2RegisterImm12Op |
| 342 RegisterList Load2RegisterImm12Op::defs(Instruction i) const { |
| 343 return immediate_addressing_defs(i).Add(t.reg(i)); |
| 344 } |
| 345 |
| 346 bool Load2RegisterImm12Op::offset_is_immediate(Instruction i) const { |
| 347 UNREFERENCED_PARAMETER(i); |
| 348 return true; |
| 349 } |
| 350 |
| 351 // Store2RegisterImm12Op |
| 352 RegisterList Store2RegisterImm12Op::defs(Instruction i) const { |
| 291 return immediate_addressing_defs(i); | 353 return immediate_addressing_defs(i); |
| 292 } | 354 } |
| 293 | 355 |
| 294 // LoadStore3RegisterOp | 356 // LoadStore3RegisterOp |
| 295 SafetyLevel LoadStore3RegisterOp::safety(const Instruction i) const { | 357 SafetyLevel LoadStore3RegisterOp::safety(const Instruction i) const { |
| 296 if (indexing.IsPreIndexing(i)) { | 358 if (indexing.IsPreIndexing(i)) { |
| 297 // If pre-indexing is set, the address of the load is computed as the sum | 359 // If pre-indexing is set, the address of the load is computed as the sum |
| 298 // of the two register parameters. We have checked that the first register | 360 // of the two register parameters. We have checked that the first register |
| 299 // is within the sandbox, but this would allow adding an arbitrary value | 361 // is within the sandbox, but this would allow adding an arbitrary value |
| 300 // to it, so it is not safe. (NaCl constraint). | 362 // to it, so it is not safe. (NaCl constraint). |
| 301 return FORBIDDEN; | 363 return FORBIDDEN; |
| 302 } | 364 } |
| 303 | 365 |
| 304 // Arm restrictions for this instruction. | 366 // Arm restrictions for this instruction. |
| 305 if (RegisterList(t.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { | 367 if (RegisterList(t.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { |
| 306 return UNPREDICTABLE; | 368 return UNPREDICTABLE; |
| 307 } | 369 } |
| 308 | 370 |
| 309 if (HasWriteBack(i) && | 371 if (HasWriteBack(i) && |
| 310 (n.reg(i).Equals(kRegisterPc) || n.reg(i).Equals(t.reg(i)))) { | 372 (n.reg(i).Equals(kRegisterPc) || |
| 373 // NOTE: The manual states that that it is also unpredictable |
| 374 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 375 // may not check for this. For the moment, we are changing |
| 376 // the code to ignore this case for stores. |
| 377 // TODO(karl): Should we not allow this? |
| 378 (is_load_ && n.reg(i).Equals(t.reg(i))))) { |
| 311 return UNPREDICTABLE; | 379 return UNPREDICTABLE; |
| 312 } | 380 } |
| 313 | 381 |
| 314 // Don't let addressing writeback alter PC (NaCl constraint). | 382 // Don't let addressing writeback alter PC (NaCl constraint). |
| 315 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; | 383 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 316 | 384 |
| 317 return MAY_BE_SAFE; | 385 return MAY_BE_SAFE; |
| 318 } | 386 } |
| 319 | 387 |
| 320 Register LoadStore3RegisterOp::base_address_register( | 388 Register LoadStore3RegisterOp::base_address_register( |
| (...skipping 23 matching lines...) Expand all Loading... |
| 344 SafetyLevel LoadStore3RegisterDoubleOp::safety(const Instruction i) const { | 412 SafetyLevel LoadStore3RegisterDoubleOp::safety(const Instruction i) const { |
| 345 // Arm restrictions for this instruction, based on double width. | 413 // Arm restrictions for this instruction, based on double width. |
| 346 if (!t.IsEven(i)) { | 414 if (!t.IsEven(i)) { |
| 347 return UNDEFINED; | 415 return UNDEFINED; |
| 348 } | 416 } |
| 349 | 417 |
| 350 if (RegisterList(t2.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { | 418 if (RegisterList(t2.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { |
| 351 return UNPREDICTABLE; | 419 return UNPREDICTABLE; |
| 352 } | 420 } |
| 353 | 421 |
| 354 if (HasWriteBack(i) && n.reg(i).Equals(t2.reg(i))) { | 422 // NOTE: The manual states that that it is also unpredictable |
| 423 // when HasWriteBack(i) and Rn=Rt2. However, the compilers |
| 424 // may not check for this. For the moment, we are changing |
| 425 // the code to ignore this case for stores. |
| 426 // TODO(karl): Should we not allow this? |
| 427 if (is_load_ && HasWriteBack(i) && n.reg(i).Equals(t2.reg(i))) { |
| 355 return UNPREDICTABLE; | 428 return UNPREDICTABLE; |
| 356 } | 429 } |
| 357 | 430 |
| 358 // Now apply non-double width restrictions for this instruction. | 431 // Now apply non-double width restrictions for this instruction. |
| 359 return LoadStore3RegisterOp::safety(i); | 432 return LoadStore3RegisterOp::safety(i); |
| 360 } | 433 } |
| 361 | 434 |
| 362 // Load3RegisterDoubleOp | 435 // Load3RegisterDoubleOp |
| 363 RegisterList Load3RegisterDoubleOp::defs(const Instruction i) const { | 436 RegisterList Load3RegisterDoubleOp::defs(const Instruction i) const { |
| 364 RegisterList defines; | 437 RegisterList defines; |
| 365 defines.Add(t.reg(i)).Add(t2.reg(i)); | 438 defines.Add(t.reg(i)).Add(t2.reg(i)); |
| 366 if (HasWriteBack(i)) { | 439 if (HasWriteBack(i)) { |
| 367 defines.Add(n.reg(i)); | 440 defines.Add(n.reg(i)); |
| 368 } | 441 } |
| 369 return defines; | 442 return defines; |
| 370 } | 443 } |
| 371 | 444 |
| 372 // Store3RegisterDoubleOp | 445 // Store3RegisterDoubleOp |
| 373 RegisterList Store3RegisterDoubleOp::defs(Instruction i) const { | 446 RegisterList Store3RegisterDoubleOp::defs(Instruction i) const { |
| 374 RegisterList defines; | 447 RegisterList defines; |
| 375 if (HasWriteBack(i)) { | 448 if (HasWriteBack(i)) { |
| 376 defines.Add(n.reg(i)); | 449 defines.Add(n.reg(i)); |
| 377 } | 450 } |
| 378 return defines; | 451 return defines; |
| 379 } | 452 } |
| 380 | 453 |
| 454 // LoadStore3RegisterImm5Op |
| 455 SafetyLevel LoadStore3RegisterImm5Op::safety(const Instruction i) const { |
| 456 if (indexing.IsPreIndexing(i)) { |
| 457 // If pre-indexing is set, the address of the load is computed as the sum |
| 458 // of the two register parameters. We have checked that the first register |
| 459 // is within the sandbox, but this would allow adding an arbitrary value |
| 460 // to it, so it is not safe. (NaCl constraint). |
| 461 return FORBIDDEN; |
| 462 } |
| 463 |
| 464 // Arm restrictions for this instruction. |
| 465 if (m.reg(i).Equals(kRegisterPc)) { |
| 466 return UNPREDICTABLE; |
| 467 } |
| 468 |
| 469 if (HasWriteBack(i) && |
| 470 (n.reg(i).Equals(kRegisterPc) || |
| 471 // NOTE: The manual states that that it is also unpredictable |
| 472 // when HasWriteBack(i) and Rn=Rt2. However, the compilers |
| 473 // may not check for this. For the moment, we are changing |
| 474 // the code to ignore this case for stores. |
| 475 // TODO(karl): Should we not allow this? |
| 476 (is_load_ && n.reg(i).Equals(t.reg(i))))) { |
| 477 return UNPREDICTABLE; |
| 478 } |
| 479 |
| 480 // Don't let Rt be Pc (NaCl constraint -- See header file for special |
| 481 // note). |
| 482 if (t.reg(i).Equals(kRegisterPc)) { |
| 483 return FORBIDDEN_OPERANDS; |
| 484 } |
| 485 |
| 486 // Don't let addressing writeback alter PC (NaCl constraint). |
| 487 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 488 |
| 489 return MAY_BE_SAFE; |
| 490 } |
| 491 |
| 492 Register LoadStore3RegisterImm5Op::base_address_register( |
| 493 const Instruction i) const { |
| 494 return n.reg(i); |
| 495 } |
| 496 |
| 497 // Load3RegisterImm5Op |
| 498 RegisterList Load3RegisterImm5Op::defs(const Instruction i) const { |
| 499 RegisterList defines(t.reg(i)); |
| 500 if (HasWriteBack(i)) { |
| 501 defines.Add(n.reg(i)); |
| 502 } |
| 503 return defines; |
| 504 } |
| 505 |
| 506 // Store3RegisterImm5Op |
| 507 RegisterList Store3RegisterImm5Op::defs(Instruction i) const { |
| 508 RegisterList defines; |
| 509 if (HasWriteBack(i)) { |
| 510 defines.Add(n.reg(i)); |
| 511 } |
| 512 return defines; |
| 513 } |
| 514 |
| 381 // Unary2RegisterImmedShiftedOp | 515 // Unary2RegisterImmedShiftedOp |
| 382 SafetyLevel Unary2RegisterImmedShiftedOp::safety(const Instruction i) const { | 516 SafetyLevel Unary2RegisterImmedShiftedOp::safety(const Instruction i) const { |
| 383 // NaCl Constraint. | 517 // NaCl Constraint. |
| 384 if (d.reg(i).Equals(kRegisterPc)) return FORBIDDEN_OPERANDS; | 518 if (d.reg(i).Equals(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 385 return MAY_BE_SAFE; | 519 return MAY_BE_SAFE; |
| 386 } | 520 } |
| 387 | 521 |
| 388 RegisterList Unary2RegisterImmedShiftedOp::defs(const Instruction i) const { | 522 RegisterList Unary2RegisterImmedShiftedOp::defs(const Instruction i) const { |
| 389 return RegisterList(d.reg(i)).Add(conditions.conds_if_updated(i)); | 523 return RegisterList(d.reg(i)).Add(conditions.conds_if_updated(i)); |
| 390 } | 524 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 if (RegisterList(n.reg(i)).Add(s.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) | 582 if (RegisterList(n.reg(i)).Add(s.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) |
| 449 return UNPREDICTABLE; | 583 return UNPREDICTABLE; |
| 450 return MAY_BE_SAFE; | 584 return MAY_BE_SAFE; |
| 451 } | 585 } |
| 452 | 586 |
| 453 RegisterList Binary3RegisterShiftedTest::defs(const Instruction i) const { | 587 RegisterList Binary3RegisterShiftedTest::defs(const Instruction i) const { |
| 454 return RegisterList(conditions.conds_if_updated(i)); | 588 return RegisterList(conditions.conds_if_updated(i)); |
| 455 } | 589 } |
| 456 | 590 |
| 457 } // namespace | 591 } // namespace |
| OLD | NEW |