@@ -214,61 +214,75 @@ void AsmMc68000::encodeDisplacement(
214
214
}
215
215
216
216
void AsmMc68000::encodeRelativeAddr (AsmInsn &insn, AddrMode mode, const Operand &op) const {
217
- // FDxx has different base address
218
- const auto base = insn.address () + (insn.hasPostVal () ? 4 : 2 );
217
+ // FDBcc has different base address
218
+ const auto FDBcc = insn.hasPostVal ();
219
+ const auto base = insn.address () + (FDBcc ? 4 : 2 );
219
220
const auto target = op.getError () ? base : op.val .getUnsigned ();
220
221
insn.setErrorIf (op, checkAddr (target, true ));
221
- ErrorAt error;
222
222
// the branchDelta() uses addressWidth(), which is 24 bit, to
223
223
// check the range of |delta|. It is not suitable for
224
224
// M_REL32. Record errors in |error| then copy it to |insn| if
225
225
// any.
226
- const auto delta = branchDelta (base, target, error, op);
227
- const auto insnSize = insn.insnSize ();
226
+ const int32_t delta = target - base;
227
+ ErrorAt error;
228
+ if ((delta < 0 && target >= base) || (delta >= 0 && target < base))
229
+ error.setErrorIf (op, OVERFLOW_RANGE);
230
+ auto type = mode;
231
+ const auto size = insn.insnSize ();
228
232
if (mode == M_REL8) {
229
- if (insnSize == ISZ_NONE) {
233
+ if (size == ISZ_NONE) {
234
+ if (overflowDelta (delta, 16 ))
235
+ error.setErrorIf (op, OPERAND_TOO_FAR);
230
236
if (overflowDelta (delta, 8 ))
231
- goto rel16;
232
- insn.embed (static_cast <uint8_t >(delta));
233
- } else if (insnSize == ISZ_BYTE || insnSize == ISZ_SNGL) {
237
+ type = M_REL16;
238
+ } else if (size == ISZ_BYTE || size == ISZ_SNGL) {
239
+ // Mnemonics has suffix 'B' or 'S'
240
+ type = M_REL8;
234
241
if (overflowDelta (delta, 8 ))
235
242
error.setErrorIf (op, OPERAND_TOO_FAR);
236
- insn. embed ( static_cast < uint8_t >(delta));
237
- } else if (insnSize == ISZ_WORD || insnSize == ISZ_LONG) {
238
- goto rel16 ;
243
+ } else if (size == ISZ_WORD || size == ISZ_LONG) {
244
+ // Mnemonics has suffix 'W' or 'L'
245
+ type = M_REL16 ;
239
246
} else {
240
- error. setErrorIf (ILLEGAL_SIZE) ;
247
+ type = M_NONE ;
241
248
}
242
249
} else if (mode == M_REL16) {
243
- if (insnSize == ISZ_NONE || insnSize == ISZ_WORD || insnSize == ISZ_LONG) {
244
- rel16:
250
+ if (size == ISZ_NONE || size == ISZ_WORD || size == ISZ_LONG) {
251
+ // Mnemonics has suffix 'W' or 'L'
245
252
if (overflowDelta (delta, 16 ))
246
253
error.setErrorIf (op, OPERAND_TOO_FAR);
247
254
} else {
248
- error. setErrorIf (ILLEGAL_SIZE) ;
255
+ type = M_NONE ;
249
256
}
250
- insn.emitOperand16 (delta);
251
- } else if (mode == M_REL32) {
252
- if (insnSize == ISZ_NONE) {
257
+ } else { // mode == M_REL32
258
+ if (size == ISZ_NONE) {
253
259
if (!overflowDelta (delta, 16 ))
254
- goto rel32_16;
255
- goto rel32;
256
- } else if (insnSize == ISZ_WORD || insnSize == ISZ_LONG) {
260
+ type = M_REL16;
261
+ error.setOK (); // never overflow
262
+ } else if (size == ISZ_WORD || size == ISZ_LONG) {
263
+ // Mnemonics has suffix 'W' or 'L'
264
+ type = M_REL16;
257
265
if (overflowDelta (delta, 16 ))
258
266
error.setErrorIf (op, OPERAND_TOO_FAR);
259
- rel32_16:
260
- insn.setOpCode (insn.opCode () & ~(1 << 6 )); // M_REL16
261
- insn.emitOperand16 (static_cast <uint16_t >(delta));
262
- } else if (insnSize == ISZ_LONG || insnSize == ISZ_XTND) {
263
- rel32:
264
- error.setOK (); // M_REL32 never overflow.
265
- insn.embed (1 << 6 ); // M_REL32
266
- insn.emitOperand32 (target - base); // 32 bit delta
267
+ } else if (size == ISZ_XTND) {
268
+ // Mnemonics has suffix ''X'
267
269
} else {
268
- error.setErrorIf (ILLEGAL_SIZE);
269
- goto rel32_16;
270
+ type = M_NONE;
270
271
}
271
272
}
273
+ if (type == M_NONE) {
274
+ error.setErrorIf (op, ILLEGAL_SIZE);
275
+ type = mode;
276
+ }
277
+ if (type == M_REL8) {
278
+ insn.embed (static_cast <uint8_t >(delta));
279
+ } else if (type == M_REL16) {
280
+ insn.emitOperand16 (delta);
281
+ } else { // type == M_REL32
282
+ insn.emitOperand32 (delta);
283
+ if (mode == M_REL32)
284
+ insn.embed (1 << 6 ); // set SIZE bit
285
+ }
272
286
// Copy error if any
273
287
insn.setErrorIf (error);
274
288
}
@@ -499,10 +513,6 @@ Error AsmMc68000::encodeOperand(
499
513
encodeImmediate (insn, op, size);
500
514
break ;
501
515
case M_LABEL:
502
- if (size == SZ_BYTE && mode == M_REL16)
503
- insn.setErrorIf (op, ILLEGAL_SIZE);
504
- if (size == SZ_WORD && mode == M_REL8)
505
- mode = M_REL16;
506
516
encodeRelativeAddr (insn, mode, op);
507
517
break ;
508
518
case M_FPREG:
0 commit comments