gemba 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/THIRD_PARTY_NOTICES +37 -2
- data/assets/placeholder_boxart.png +0 -0
- data/bin/gemba +2 -2
- data/ext/gemba/extconf.rb +24 -1
- data/ext/gemba/gemba_ext.c +436 -2
- data/ext/gemba/gemba_ext.h +2 -0
- data/gemba.gemspec +5 -3
- data/lib/gemba/achievements/achievement.rb +23 -0
- data/lib/gemba/achievements/backend.rb +186 -0
- data/lib/gemba/achievements/cache.rb +70 -0
- data/lib/gemba/achievements/credentials_presenter.rb +142 -0
- data/lib/gemba/achievements/fake_backend.rb +205 -0
- data/lib/gemba/achievements/null_backend.rb +11 -0
- data/lib/gemba/achievements/offline_backend.rb +168 -0
- data/lib/gemba/achievements/retro_achievements/backend.rb +453 -0
- data/lib/gemba/achievements/retro_achievements/cli_sync_requester.rb +64 -0
- data/lib/gemba/achievements/retro_achievements/ping_worker.rb +27 -0
- data/lib/gemba/achievements.rb +19 -0
- data/lib/gemba/achievements_window.rb +556 -0
- data/lib/gemba/app_controller.rb +1015 -0
- data/lib/gemba/bios.rb +54 -0
- data/lib/gemba/boxart_fetcher/libretro_backend.rb +39 -0
- data/lib/gemba/boxart_fetcher/null_backend.rb +12 -0
- data/lib/gemba/boxart_fetcher.rb +79 -0
- data/lib/gemba/bus_emitter.rb +13 -0
- data/lib/gemba/child_window.rb +24 -1
- data/lib/gemba/cli/commands/config_cmd.rb +83 -0
- data/lib/gemba/cli/commands/decode.rb +154 -0
- data/lib/gemba/cli/commands/patch.rb +78 -0
- data/lib/gemba/cli/commands/play.rb +78 -0
- data/lib/gemba/cli/commands/record.rb +114 -0
- data/lib/gemba/cli/commands/replay.rb +161 -0
- data/lib/gemba/cli/commands/retro_achievements.rb +213 -0
- data/lib/gemba/cli/commands/version.rb +22 -0
- data/lib/gemba/cli.rb +52 -364
- data/lib/gemba/config.rb +135 -1
- data/lib/gemba/data/gb_games.json +1 -0
- data/lib/gemba/data/gb_md5.json +1 -0
- data/lib/gemba/data/gba_games.json +1 -0
- data/lib/gemba/data/gba_md5.json +1 -0
- data/lib/gemba/data/gbc_games.json +1 -0
- data/lib/gemba/data/gbc_md5.json +1 -0
- data/lib/gemba/emulator_frame.rb +1060 -0
- data/lib/gemba/event_bus.rb +48 -0
- data/lib/gemba/frame_stack.rb +60 -0
- data/lib/gemba/game_index.rb +84 -0
- data/lib/gemba/game_picker_frame.rb +268 -0
- data/lib/gemba/gamepad_map.rb +103 -0
- data/lib/gemba/headless.rb +6 -5
- data/lib/gemba/headless_player.rb +33 -3
- data/lib/gemba/help_window.rb +61 -0
- data/lib/gemba/hotkey_map.rb +3 -1
- data/lib/gemba/input_recorder.rb +107 -0
- data/lib/gemba/input_replayer.rb +119 -0
- data/lib/gemba/keyboard_map.rb +90 -0
- data/lib/gemba/locales/en.yml +97 -5
- data/lib/gemba/locales/ja.yml +97 -5
- data/lib/gemba/main_window.rb +56 -0
- data/lib/gemba/modal_stack.rb +81 -0
- data/lib/gemba/patcher_window.rb +223 -0
- data/lib/gemba/platform/gb.rb +21 -0
- data/lib/gemba/platform/gba.rb +21 -0
- data/lib/gemba/platform/gbc.rb +23 -0
- data/lib/gemba/platform.rb +20 -0
- data/lib/gemba/platform_open.rb +19 -0
- data/lib/gemba/recorder.rb +4 -3
- data/lib/gemba/replay_player.rb +691 -0
- data/lib/gemba/rom_info.rb +57 -0
- data/lib/gemba/rom_info_window.rb +16 -3
- data/lib/gemba/rom_library.rb +106 -0
- data/lib/gemba/rom_overrides.rb +47 -0
- data/lib/gemba/rom_patcher/bps.rb +161 -0
- data/lib/gemba/rom_patcher/ips.rb +101 -0
- data/lib/gemba/rom_patcher/ups.rb +118 -0
- data/lib/gemba/rom_patcher.rb +109 -0
- data/lib/gemba/{rom_loader.rb → rom_resolver.rb} +7 -6
- data/lib/gemba/runtime.rb +59 -26
- data/lib/gemba/save_state_manager.rb +4 -7
- data/lib/gemba/save_state_picker.rb +17 -4
- data/lib/gemba/session_logger.rb +64 -0
- data/lib/gemba/settings/audio_tab.rb +77 -0
- data/lib/gemba/settings/gamepad_tab.rb +351 -0
- data/lib/gemba/settings/hotkeys_tab.rb +259 -0
- data/lib/gemba/settings/paths.rb +11 -0
- data/lib/gemba/settings/recording_tab.rb +83 -0
- data/lib/gemba/settings/save_states_tab.rb +91 -0
- data/lib/gemba/settings/system_tab.rb +362 -0
- data/lib/gemba/settings/video_tab.rb +318 -0
- data/lib/gemba/settings_window.rb +162 -1036
- data/lib/gemba/version.rb +1 -1
- data/lib/gemba/virtual_keyboard.rb +19 -0
- data/lib/gemba.rb +2 -12
- data/test/achievements_window/test_bulk_sync.rb +218 -0
- data/test/achievements_window/test_bus_events.rb +125 -0
- data/test/achievements_window/test_close_confirmation.rb +201 -0
- data/test/achievements_window/test_initial_state.rb +164 -0
- data/test/achievements_window/test_sorting.rb +227 -0
- data/test/achievements_window/test_tree_rendering.rb +133 -0
- data/test/fixtures/fake_bios.bin +0 -0
- data/test/fixtures/pong.gba +0 -0
- data/test/fixtures/test.gb +0 -0
- data/test/fixtures/test.gbc +0 -0
- data/test/fixtures/test_quicksave.ss +0 -0
- data/test/screenshots/no_focus.png +0 -0
- data/test/shared/teek_test_worker.rb +17 -1
- data/test/shared/tk_test_helper.rb +91 -4
- data/test/support/achievements_window_helpers.rb +18 -0
- data/test/support/fake_core.rb +25 -0
- data/test/support/fake_ra_runtime.rb +74 -0
- data/test/support/fake_requester.rb +68 -0
- data/test/support/player_helpers.rb +20 -5
- data/test/test_achievement.rb +32 -0
- data/test/{test_player.rb → test_app_controller.rb} +353 -85
- data/test/test_bios.rb +123 -0
- data/test/test_boxart_fetcher.rb +150 -0
- data/test/test_cli.rb +17 -265
- data/test/test_cli_config.rb +64 -0
- data/test/test_cli_decode.rb +97 -0
- data/test/test_cli_patch.rb +58 -0
- data/test/test_cli_play.rb +213 -0
- data/test/test_cli_ra.rb +175 -0
- data/test/test_cli_record.rb +69 -0
- data/test/test_cli_replay.rb +72 -0
- data/test/test_cli_sync_requester.rb +152 -0
- data/test/test_cli_version.rb +27 -0
- data/test/test_config.rb +2 -3
- data/test/test_config_ra.rb +69 -0
- data/test/test_core.rb +62 -1
- data/test/test_credentials_presenter.rb +192 -0
- data/test/test_event_bus.rb +100 -0
- data/test/test_fake_backend_achievements.rb +130 -0
- data/test/test_fake_backend_auth.rb +68 -0
- data/test/test_game_index.rb +77 -0
- data/test/test_game_picker_frame.rb +310 -0
- data/test/test_gamepad_map.rb +1 -3
- data/test/test_headless_player.rb +17 -3
- data/test/test_help_window.rb +82 -0
- data/test/test_hotkey_map.rb +22 -1
- data/test/test_input_recorder.rb +179 -0
- data/test/test_input_replay_determinism.rb +113 -0
- data/test/test_input_replayer.rb +162 -0
- data/test/test_keyboard_map.rb +1 -3
- data/test/test_libretro_backend.rb +41 -0
- data/test/test_locale.rb +1 -1
- data/test/test_logging.rb +123 -0
- data/test/test_null_backend.rb +42 -0
- data/test/test_offline_backend.rb +116 -0
- data/test/test_overlay_renderer.rb +1 -1
- data/test/test_platform.rb +149 -0
- data/test/test_ra_backend.rb +313 -0
- data/test/test_ra_backend_unlock_gate.rb +56 -0
- data/test/test_recorder.rb +0 -3
- data/test/test_replay_player.rb +316 -0
- data/test/test_rom_info.rb +149 -0
- data/test/test_rom_overrides.rb +86 -0
- data/test/test_rom_patcher.rb +382 -0
- data/test/{test_rom_loader.rb → test_rom_resolver.rb} +25 -26
- data/test/test_save_state_manager.rb +2 -4
- data/test/test_settings_audio.rb +107 -0
- data/test/test_settings_hotkeys.rb +83 -66
- data/test/test_settings_recording.rb +49 -0
- data/test/test_settings_save_states.rb +97 -0
- data/test/test_settings_system.rb +133 -0
- data/test/test_settings_video.rb +450 -0
- data/test/test_settings_window.rb +76 -507
- data/test/test_tip_service.rb +6 -6
- data/test/test_toast_overlay.rb +1 -1
- data/test/test_virtual_events.rb +156 -0
- data/test/test_virtual_keyboard.rb +1 -1
- data/vendor/rcheevos/CHANGELOG.md +495 -0
- data/vendor/rcheevos/LICENSE +21 -0
- data/vendor/rcheevos/Package.swift +33 -0
- data/vendor/rcheevos/README.md +67 -0
- data/vendor/rcheevos/include/module.modulemap +70 -0
- data/vendor/rcheevos/include/rc_api_editor.h +296 -0
- data/vendor/rcheevos/include/rc_api_info.h +280 -0
- data/vendor/rcheevos/include/rc_api_request.h +77 -0
- data/vendor/rcheevos/include/rc_api_runtime.h +417 -0
- data/vendor/rcheevos/include/rc_api_user.h +262 -0
- data/vendor/rcheevos/include/rc_client.h +877 -0
- data/vendor/rcheevos/include/rc_client_raintegration.h +101 -0
- data/vendor/rcheevos/include/rc_consoles.h +138 -0
- data/vendor/rcheevos/include/rc_error.h +59 -0
- data/vendor/rcheevos/include/rc_export.h +100 -0
- data/vendor/rcheevos/include/rc_hash.h +200 -0
- data/vendor/rcheevos/include/rc_runtime.h +148 -0
- data/vendor/rcheevos/include/rc_runtime_types.h +452 -0
- data/vendor/rcheevos/include/rc_util.h +51 -0
- data/vendor/rcheevos/include/rcheevos.h +8 -0
- data/vendor/rcheevos/src/rapi/rc_api_common.c +1379 -0
- data/vendor/rcheevos/src/rapi/rc_api_common.h +88 -0
- data/vendor/rcheevos/src/rapi/rc_api_editor.c +625 -0
- data/vendor/rcheevos/src/rapi/rc_api_info.c +587 -0
- data/vendor/rcheevos/src/rapi/rc_api_runtime.c +901 -0
- data/vendor/rcheevos/src/rapi/rc_api_user.c +483 -0
- data/vendor/rcheevos/src/rc_client.c +6941 -0
- data/vendor/rcheevos/src/rc_client_external.c +281 -0
- data/vendor/rcheevos/src/rc_client_external.h +177 -0
- data/vendor/rcheevos/src/rc_client_external_versions.h +171 -0
- data/vendor/rcheevos/src/rc_client_internal.h +409 -0
- data/vendor/rcheevos/src/rc_client_raintegration.c +566 -0
- data/vendor/rcheevos/src/rc_client_raintegration_internal.h +61 -0
- data/vendor/rcheevos/src/rc_client_types.natvis +396 -0
- data/vendor/rcheevos/src/rc_compat.c +251 -0
- data/vendor/rcheevos/src/rc_compat.h +121 -0
- data/vendor/rcheevos/src/rc_libretro.c +915 -0
- data/vendor/rcheevos/src/rc_libretro.h +98 -0
- data/vendor/rcheevos/src/rc_util.c +199 -0
- data/vendor/rcheevos/src/rc_version.c +11 -0
- data/vendor/rcheevos/src/rc_version.h +32 -0
- data/vendor/rcheevos/src/rcheevos/alloc.c +312 -0
- data/vendor/rcheevos/src/rcheevos/condition.c +754 -0
- data/vendor/rcheevos/src/rcheevos/condset.c +777 -0
- data/vendor/rcheevos/src/rcheevos/consoleinfo.c +1215 -0
- data/vendor/rcheevos/src/rcheevos/format.c +330 -0
- data/vendor/rcheevos/src/rcheevos/lboard.c +287 -0
- data/vendor/rcheevos/src/rcheevos/memref.c +805 -0
- data/vendor/rcheevos/src/rcheevos/operand.c +607 -0
- data/vendor/rcheevos/src/rcheevos/rc_internal.h +390 -0
- data/vendor/rcheevos/src/rcheevos/rc_runtime_types.natvis +541 -0
- data/vendor/rcheevos/src/rcheevos/rc_validate.c +1406 -0
- data/vendor/rcheevos/src/rcheevos/rc_validate.h +18 -0
- data/vendor/rcheevos/src/rcheevos/richpresence.c +922 -0
- data/vendor/rcheevos/src/rcheevos/runtime.c +852 -0
- data/vendor/rcheevos/src/rcheevos/runtime_progress.c +1073 -0
- data/vendor/rcheevos/src/rcheevos/trigger.c +344 -0
- data/vendor/rcheevos/src/rcheevos/value.c +935 -0
- data/vendor/rcheevos/src/rhash/aes.c +480 -0
- data/vendor/rcheevos/src/rhash/aes.h +49 -0
- data/vendor/rcheevos/src/rhash/cdreader.c +838 -0
- data/vendor/rcheevos/src/rhash/hash.c +1402 -0
- data/vendor/rcheevos/src/rhash/hash_disc.c +1340 -0
- data/vendor/rcheevos/src/rhash/hash_encrypted.c +566 -0
- data/vendor/rcheevos/src/rhash/hash_rom.c +426 -0
- data/vendor/rcheevos/src/rhash/hash_zip.c +460 -0
- data/vendor/rcheevos/src/rhash/md5.c +382 -0
- data/vendor/rcheevos/src/rhash/md5.h +91 -0
- data/vendor/rcheevos/src/rhash/rc_hash_internal.h +116 -0
- data/vendor/rcheevos/test/libretro.h +205 -0
- data/vendor/rcheevos/test/rapi/test_rc_api_common.c +941 -0
- data/vendor/rcheevos/test/rapi/test_rc_api_editor.c +931 -0
- data/vendor/rcheevos/test/rapi/test_rc_api_info.c +545 -0
- data/vendor/rcheevos/test/rapi/test_rc_api_runtime.c +2213 -0
- data/vendor/rcheevos/test/rapi/test_rc_api_user.c +998 -0
- data/vendor/rcheevos/test/rcheevos/mock_memory.h +32 -0
- data/vendor/rcheevos/test/rcheevos/test_condition.c +570 -0
- data/vendor/rcheevos/test/rcheevos/test_condset.c +5170 -0
- data/vendor/rcheevos/test/rcheevos/test_consoleinfo.c +203 -0
- data/vendor/rcheevos/test/rcheevos/test_format.c +112 -0
- data/vendor/rcheevos/test/rcheevos/test_lboard.c +746 -0
- data/vendor/rcheevos/test/rcheevos/test_memref.c +520 -0
- data/vendor/rcheevos/test/rcheevos/test_operand.c +692 -0
- data/vendor/rcheevos/test/rcheevos/test_rc_validate.c +502 -0
- data/vendor/rcheevos/test/rcheevos/test_richpresence.c +1564 -0
- data/vendor/rcheevos/test/rcheevos/test_runtime.c +1667 -0
- data/vendor/rcheevos/test/rcheevos/test_runtime_progress.c +1821 -0
- data/vendor/rcheevos/test/rcheevos/test_timing.c +166 -0
- data/vendor/rcheevos/test/rcheevos/test_trigger.c +2521 -0
- data/vendor/rcheevos/test/rcheevos/test_value.c +870 -0
- data/vendor/rcheevos/test/rcheevos-test.sln +46 -0
- data/vendor/rcheevos/test/rcheevos-test.vcxproj +239 -0
- data/vendor/rcheevos/test/rcheevos-test.vcxproj.filters +335 -0
- data/vendor/rcheevos/test/rhash/data.c +657 -0
- data/vendor/rcheevos/test/rhash/data.h +32 -0
- data/vendor/rcheevos/test/rhash/mock_filereader.c +236 -0
- data/vendor/rcheevos/test/rhash/mock_filereader.h +31 -0
- data/vendor/rcheevos/test/rhash/test_cdreader.c +920 -0
- data/vendor/rcheevos/test/rhash/test_hash.c +310 -0
- data/vendor/rcheevos/test/rhash/test_hash_disc.c +1450 -0
- data/vendor/rcheevos/test/rhash/test_hash_rom.c +899 -0
- data/vendor/rcheevos/test/rhash/test_hash_zip.c +551 -0
- data/vendor/rcheevos/test/test.c +113 -0
- data/vendor/rcheevos/test/test_framework.h +205 -0
- data/vendor/rcheevos/test/test_rc_client.c +10509 -0
- data/vendor/rcheevos/test/test_rc_client_external.c +2197 -0
- data/vendor/rcheevos/test/test_rc_client_raintegration.c +441 -0
- data/vendor/rcheevos/test/test_rc_libretro.c +952 -0
- data/vendor/rcheevos/test/test_types.natvis +9 -0
- data/vendor/rcheevos/validator/validator.c +658 -0
- data/vendor/rcheevos/validator/validator.vcxproj +152 -0
- data/vendor/rcheevos/validator/validator.vcxproj.filters +82 -0
- metadata +274 -11
- data/lib/gemba/input_mappings.rb +0 -214
- data/lib/gemba/player.rb +0 -1515
|
@@ -0,0 +1,805 @@
|
|
|
1
|
+
#include "rc_internal.h"
|
|
2
|
+
|
|
3
|
+
#include <stdlib.h> /* malloc/realloc */
|
|
4
|
+
#include <string.h> /* memcpy */
|
|
5
|
+
#include <math.h> /* INFINITY/NAN */
|
|
6
|
+
|
|
7
|
+
#define MEMREF_PLACEHOLDER_ADDRESS 0xFFFFFFFF
|
|
8
|
+
|
|
9
|
+
rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size) {
|
|
10
|
+
rc_memref_list_t* memref_list = NULL;
|
|
11
|
+
rc_memref_t* memref = NULL;
|
|
12
|
+
int i;
|
|
13
|
+
|
|
14
|
+
for (i = 0; i < 2; i++) {
|
|
15
|
+
if (i == 0) {
|
|
16
|
+
if (!parse->existing_memrefs)
|
|
17
|
+
continue;
|
|
18
|
+
|
|
19
|
+
memref_list = &parse->existing_memrefs->memrefs;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
memref_list = &parse->memrefs->memrefs;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
do
|
|
26
|
+
{
|
|
27
|
+
const rc_memref_t* memref_stop;
|
|
28
|
+
|
|
29
|
+
memref = memref_list->items;
|
|
30
|
+
memref_stop = memref + memref_list->count;
|
|
31
|
+
|
|
32
|
+
for (; memref < memref_stop; ++memref) {
|
|
33
|
+
if (memref->address == address && memref->value.size == size)
|
|
34
|
+
return memref;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!memref_list->next)
|
|
38
|
+
break;
|
|
39
|
+
|
|
40
|
+
memref_list = memref_list->next;
|
|
41
|
+
} while (1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* no match found, find a place to put the new entry */
|
|
45
|
+
memref_list = &parse->memrefs->memrefs;
|
|
46
|
+
while (memref_list->count == memref_list->capacity && memref_list->next)
|
|
47
|
+
memref_list = memref_list->next;
|
|
48
|
+
|
|
49
|
+
/* create a new entry */
|
|
50
|
+
if (memref_list->count < memref_list->capacity) {
|
|
51
|
+
memref = &memref_list->items[memref_list->count++];
|
|
52
|
+
} else {
|
|
53
|
+
const int32_t old_offset = parse->offset;
|
|
54
|
+
|
|
55
|
+
if (memref_list->capacity != 0) {
|
|
56
|
+
memref_list = memref_list->next = RC_ALLOC_SCRATCH(rc_memref_list_t, parse);
|
|
57
|
+
memref_list->next = NULL;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
memref_list->items = RC_ALLOC_ARRAY_SCRATCH(rc_memref_t, 8, parse);
|
|
61
|
+
memref_list->count = 1;
|
|
62
|
+
memref_list->capacity = 8;
|
|
63
|
+
memref_list->allocated = 0;
|
|
64
|
+
|
|
65
|
+
memref = memref_list->items;
|
|
66
|
+
|
|
67
|
+
/* in preparse mode, don't count this memory, we'll do a single allocation once we have
|
|
68
|
+
* the final total */
|
|
69
|
+
if (!parse->buffer)
|
|
70
|
+
parse->offset = old_offset;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
memset(memref, 0, sizeof(*memref));
|
|
74
|
+
memref->value.memref_type = RC_MEMREF_TYPE_MEMREF;
|
|
75
|
+
memref->value.type = RC_VALUE_TYPE_UNSIGNED;
|
|
76
|
+
memref->value.size = size;
|
|
77
|
+
memref->address = address;
|
|
78
|
+
|
|
79
|
+
return memref;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
rc_modified_memref_t* rc_alloc_modified_memref(rc_parse_state_t* parse, uint8_t size, const rc_operand_t* parent,
|
|
83
|
+
uint8_t modifier_type, const rc_operand_t* modifier) {
|
|
84
|
+
rc_modified_memref_list_t* modified_memref_list = NULL;
|
|
85
|
+
rc_modified_memref_t* modified_memref = NULL;
|
|
86
|
+
int i = 0;
|
|
87
|
+
|
|
88
|
+
for (i = 0; i < 2; i++) {
|
|
89
|
+
if (i == 0) {
|
|
90
|
+
if (!parse->existing_memrefs)
|
|
91
|
+
continue;
|
|
92
|
+
|
|
93
|
+
modified_memref_list = &parse->existing_memrefs->modified_memrefs;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
modified_memref_list = &parse->memrefs->modified_memrefs;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
do {
|
|
100
|
+
const rc_modified_memref_t* memref_stop;
|
|
101
|
+
|
|
102
|
+
modified_memref = modified_memref_list->items;
|
|
103
|
+
memref_stop = modified_memref + modified_memref_list->count;
|
|
104
|
+
|
|
105
|
+
for (; modified_memref < memref_stop; ++modified_memref) {
|
|
106
|
+
if (modified_memref->memref.value.size == size &&
|
|
107
|
+
modified_memref->modifier_type == modifier_type &&
|
|
108
|
+
rc_operands_are_equal(&modified_memref->parent, parent) &&
|
|
109
|
+
rc_operands_are_equal(&modified_memref->modifier, modifier)) {
|
|
110
|
+
return modified_memref;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!modified_memref_list->next)
|
|
115
|
+
break;
|
|
116
|
+
|
|
117
|
+
modified_memref_list = modified_memref_list->next;
|
|
118
|
+
} while (1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* no match found, find a place to put the new entry */
|
|
122
|
+
modified_memref_list = &parse->memrefs->modified_memrefs;
|
|
123
|
+
while (modified_memref_list->count == modified_memref_list->capacity && modified_memref_list->next)
|
|
124
|
+
modified_memref_list = modified_memref_list->next;
|
|
125
|
+
|
|
126
|
+
/* create a new entry */
|
|
127
|
+
if (modified_memref_list->count < modified_memref_list->capacity) {
|
|
128
|
+
modified_memref = &modified_memref_list->items[modified_memref_list->count++];
|
|
129
|
+
} else {
|
|
130
|
+
const int32_t old_offset = parse->offset;
|
|
131
|
+
|
|
132
|
+
if (modified_memref_list->capacity != 0) {
|
|
133
|
+
modified_memref_list = modified_memref_list->next = RC_ALLOC_SCRATCH(rc_modified_memref_list_t, parse);
|
|
134
|
+
modified_memref_list->next = NULL;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
modified_memref_list->items = RC_ALLOC_ARRAY_SCRATCH(rc_modified_memref_t, 8, parse);
|
|
138
|
+
modified_memref_list->count = 1;
|
|
139
|
+
modified_memref_list->capacity = 8;
|
|
140
|
+
modified_memref_list->allocated = 0;
|
|
141
|
+
|
|
142
|
+
modified_memref = modified_memref_list->items;
|
|
143
|
+
|
|
144
|
+
/* in preparse mode, don't count this memory, we'll do a single allocation once we have
|
|
145
|
+
* the final total */
|
|
146
|
+
if (!parse->buffer)
|
|
147
|
+
parse->offset = old_offset;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
memset(modified_memref, 0, sizeof(*modified_memref));
|
|
151
|
+
modified_memref->memref.value.memref_type = RC_MEMREF_TYPE_MODIFIED_MEMREF;
|
|
152
|
+
modified_memref->memref.value.size = size;
|
|
153
|
+
modified_memref->memref.value.type = rc_memsize_is_float(size) ? RC_VALUE_TYPE_FLOAT : RC_VALUE_TYPE_UNSIGNED;
|
|
154
|
+
memcpy(&modified_memref->parent, parent, sizeof(modified_memref->parent));
|
|
155
|
+
memcpy(&modified_memref->modifier, modifier, sizeof(modified_memref->modifier));
|
|
156
|
+
modified_memref->modifier_type = modifier_type;
|
|
157
|
+
modified_memref->depth = 0;
|
|
158
|
+
modified_memref->memref.address = rc_operand_is_memref(modifier) ? modifier->value.memref->address : modifier->value.num;
|
|
159
|
+
|
|
160
|
+
if (rc_operand_is_memref(parent) && parent->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) {
|
|
161
|
+
const rc_modified_memref_t* parent_modified_memref = (rc_modified_memref_t*)parent->value.memref;
|
|
162
|
+
modified_memref->depth = parent_modified_memref->depth + 1;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return modified_memref;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
void rc_memrefs_init(rc_memrefs_t* memrefs)
|
|
169
|
+
{
|
|
170
|
+
memset(memrefs, 0, sizeof(*memrefs));
|
|
171
|
+
|
|
172
|
+
memrefs->memrefs.capacity = 32;
|
|
173
|
+
memrefs->memrefs.items =
|
|
174
|
+
(rc_memref_t*)malloc(memrefs->memrefs.capacity * sizeof(rc_memref_t));
|
|
175
|
+
memrefs->memrefs.allocated = 1;
|
|
176
|
+
|
|
177
|
+
memrefs->modified_memrefs.capacity = 16;
|
|
178
|
+
memrefs->modified_memrefs.items =
|
|
179
|
+
(rc_modified_memref_t*)malloc(memrefs->modified_memrefs.capacity * sizeof(rc_modified_memref_t));
|
|
180
|
+
memrefs->modified_memrefs.allocated = 1;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
void rc_memrefs_destroy(rc_memrefs_t* memrefs)
|
|
184
|
+
{
|
|
185
|
+
rc_memref_list_t* memref_list = &memrefs->memrefs;
|
|
186
|
+
rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs;
|
|
187
|
+
|
|
188
|
+
do {
|
|
189
|
+
rc_memref_list_t* current_memref_list = memref_list;
|
|
190
|
+
memref_list = memref_list->next;
|
|
191
|
+
|
|
192
|
+
if (current_memref_list->allocated) {
|
|
193
|
+
if (current_memref_list->items)
|
|
194
|
+
free(current_memref_list->items);
|
|
195
|
+
|
|
196
|
+
if (current_memref_list != &memrefs->memrefs)
|
|
197
|
+
free(current_memref_list);
|
|
198
|
+
}
|
|
199
|
+
} while (memref_list);
|
|
200
|
+
|
|
201
|
+
do {
|
|
202
|
+
rc_modified_memref_list_t* current_modified_memref_list = modified_memref_list;
|
|
203
|
+
modified_memref_list = modified_memref_list->next;
|
|
204
|
+
|
|
205
|
+
if (current_modified_memref_list->allocated) {
|
|
206
|
+
if (current_modified_memref_list->items)
|
|
207
|
+
free(current_modified_memref_list->items);
|
|
208
|
+
|
|
209
|
+
if (current_modified_memref_list != &memrefs->modified_memrefs)
|
|
210
|
+
free(current_modified_memref_list);
|
|
211
|
+
}
|
|
212
|
+
} while (modified_memref_list);
|
|
213
|
+
|
|
214
|
+
free(memrefs);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
uint32_t rc_memrefs_count_memrefs(const rc_memrefs_t* memrefs)
|
|
218
|
+
{
|
|
219
|
+
uint32_t count = 0;
|
|
220
|
+
const rc_memref_list_t* memref_list = &memrefs->memrefs;
|
|
221
|
+
while (memref_list) {
|
|
222
|
+
count += memref_list->count;
|
|
223
|
+
memref_list = memref_list->next;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return count;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
uint32_t rc_memrefs_count_modified_memrefs(const rc_memrefs_t* memrefs)
|
|
230
|
+
{
|
|
231
|
+
uint32_t count = 0;
|
|
232
|
+
const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs;
|
|
233
|
+
while (modified_memref_list) {
|
|
234
|
+
count += modified_memref_list->count;
|
|
235
|
+
modified_memref_list = modified_memref_list->next;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return count;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address) {
|
|
242
|
+
const char* aux = *memaddr;
|
|
243
|
+
char* end;
|
|
244
|
+
unsigned long value;
|
|
245
|
+
|
|
246
|
+
if (aux[0] == '0') {
|
|
247
|
+
if (aux[1] != 'x' && aux[1] != 'X')
|
|
248
|
+
return RC_INVALID_MEMORY_OPERAND;
|
|
249
|
+
|
|
250
|
+
aux += 2;
|
|
251
|
+
switch (*aux++) {
|
|
252
|
+
/* ordered by estimated frequency in case compiler doesn't build a jump table */
|
|
253
|
+
case 'h': case 'H': *size = RC_MEMSIZE_8_BITS; break;
|
|
254
|
+
case ' ': *size = RC_MEMSIZE_16_BITS; break;
|
|
255
|
+
case 'x': case 'X': *size = RC_MEMSIZE_32_BITS; break;
|
|
256
|
+
|
|
257
|
+
case 'm': case 'M': *size = RC_MEMSIZE_BIT_0; break;
|
|
258
|
+
case 'n': case 'N': *size = RC_MEMSIZE_BIT_1; break;
|
|
259
|
+
case 'o': case 'O': *size = RC_MEMSIZE_BIT_2; break;
|
|
260
|
+
case 'p': case 'P': *size = RC_MEMSIZE_BIT_3; break;
|
|
261
|
+
case 'q': case 'Q': *size = RC_MEMSIZE_BIT_4; break;
|
|
262
|
+
case 'r': case 'R': *size = RC_MEMSIZE_BIT_5; break;
|
|
263
|
+
case 's': case 'S': *size = RC_MEMSIZE_BIT_6; break;
|
|
264
|
+
case 't': case 'T': *size = RC_MEMSIZE_BIT_7; break;
|
|
265
|
+
case 'l': case 'L': *size = RC_MEMSIZE_LOW; break;
|
|
266
|
+
case 'u': case 'U': *size = RC_MEMSIZE_HIGH; break;
|
|
267
|
+
case 'k': case 'K': *size = RC_MEMSIZE_BITCOUNT; break;
|
|
268
|
+
case 'w': case 'W': *size = RC_MEMSIZE_24_BITS; break;
|
|
269
|
+
case 'g': case 'G': *size = RC_MEMSIZE_32_BITS_BE; break;
|
|
270
|
+
case 'i': case 'I': *size = RC_MEMSIZE_16_BITS_BE; break;
|
|
271
|
+
case 'j': case 'J': *size = RC_MEMSIZE_24_BITS_BE; break;
|
|
272
|
+
|
|
273
|
+
/* case 'v': case 'V': */
|
|
274
|
+
/* case 'y': case 'Y': 64 bit? */
|
|
275
|
+
/* case 'z': case 'Z': 128 bit? */
|
|
276
|
+
|
|
277
|
+
case '0':
|
|
278
|
+
if (*aux == 'x') /* user mistyped an extra 0x: 0x0xabcd */
|
|
279
|
+
return RC_INVALID_MEMORY_OPERAND;
|
|
280
|
+
/* fallthrough */
|
|
281
|
+
|
|
282
|
+
case '1': case '2': case '3': case '4':
|
|
283
|
+
case '5': case '6': case '7': case '8': case '9':
|
|
284
|
+
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
285
|
+
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
|
286
|
+
/* legacy support - addresses without a size prefix are assumed to be 16-bit */
|
|
287
|
+
aux--;
|
|
288
|
+
*size = RC_MEMSIZE_16_BITS;
|
|
289
|
+
break;
|
|
290
|
+
|
|
291
|
+
default:
|
|
292
|
+
return RC_INVALID_MEMORY_OPERAND;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
else if (aux[0] == 'f' || aux[0] == 'F') {
|
|
296
|
+
++aux;
|
|
297
|
+
switch (*aux++) {
|
|
298
|
+
case 'f': case 'F': *size = RC_MEMSIZE_FLOAT; break;
|
|
299
|
+
case 'b': case 'B': *size = RC_MEMSIZE_FLOAT_BE; break;
|
|
300
|
+
case 'h': case 'H': *size = RC_MEMSIZE_DOUBLE32; break;
|
|
301
|
+
case 'i': case 'I': *size = RC_MEMSIZE_DOUBLE32_BE; break;
|
|
302
|
+
case 'm': case 'M': *size = RC_MEMSIZE_MBF32; break;
|
|
303
|
+
case 'l': case 'L': *size = RC_MEMSIZE_MBF32_LE; break;
|
|
304
|
+
|
|
305
|
+
default:
|
|
306
|
+
return RC_INVALID_FP_OPERAND;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
return RC_INVALID_MEMORY_OPERAND;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
value = strtoul(aux, &end, 16);
|
|
314
|
+
|
|
315
|
+
if (end == aux)
|
|
316
|
+
return RC_INVALID_MEMORY_OPERAND;
|
|
317
|
+
|
|
318
|
+
if (value > 0xffffffffU)
|
|
319
|
+
value = 0xffffffffU;
|
|
320
|
+
|
|
321
|
+
*address = (uint32_t)value;
|
|
322
|
+
*memaddr = end;
|
|
323
|
+
return RC_OK;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
static float rc_build_float(uint32_t mantissa_bits, int32_t exponent, int sign) {
|
|
327
|
+
/* 32-bit float has a 23-bit mantissa and 8-bit exponent */
|
|
328
|
+
const uint32_t implied_bit = 1 << 23;
|
|
329
|
+
const uint32_t mantissa = mantissa_bits | implied_bit;
|
|
330
|
+
double dbl = ((double)mantissa) / ((double)implied_bit);
|
|
331
|
+
|
|
332
|
+
if (exponent > 127) {
|
|
333
|
+
/* exponent above 127 is a special number */
|
|
334
|
+
if (mantissa_bits == 0) {
|
|
335
|
+
/* infinity */
|
|
336
|
+
#ifdef INFINITY /* INFINITY and NAN #defines require C99 */
|
|
337
|
+
dbl = (double)INFINITY;
|
|
338
|
+
#else
|
|
339
|
+
dbl = -log(0.0);
|
|
340
|
+
#endif
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
/* NaN */
|
|
344
|
+
#ifdef NAN
|
|
345
|
+
dbl = NAN;
|
|
346
|
+
#else
|
|
347
|
+
dbl = -sqrt(-1);
|
|
348
|
+
#endif
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
else if (exponent > 0) {
|
|
352
|
+
/* exponent from 1 to 127 is a number greater than 1 */
|
|
353
|
+
while (exponent > 30) {
|
|
354
|
+
dbl *= (double)(1 << 30);
|
|
355
|
+
exponent -= 30;
|
|
356
|
+
}
|
|
357
|
+
dbl *= (double)((long long)1 << exponent);
|
|
358
|
+
}
|
|
359
|
+
else if (exponent < 0) {
|
|
360
|
+
/* exponent from -1 to -127 is a number less than 1 */
|
|
361
|
+
|
|
362
|
+
if (exponent == -127) {
|
|
363
|
+
/* exponent -127 (all exponent bits were zero) is a denormalized value
|
|
364
|
+
* (no implied leading bit) with exponent -126 */
|
|
365
|
+
dbl = ((double)mantissa_bits) / ((double)implied_bit);
|
|
366
|
+
exponent = 126;
|
|
367
|
+
} else {
|
|
368
|
+
exponent = -exponent;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
while (exponent > 30) {
|
|
372
|
+
dbl /= (double)(1 << 30);
|
|
373
|
+
exponent -= 30;
|
|
374
|
+
}
|
|
375
|
+
dbl /= (double)((long long)1 << exponent);
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
/* exponent of 0 requires no adjustment */
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return (sign) ? (float)-dbl : (float)dbl;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
static void rc_transform_memref_float(rc_typed_value_t* value) {
|
|
385
|
+
/* decodes an IEEE 754 float */
|
|
386
|
+
const uint32_t mantissa = (value->value.u32 & 0x7FFFFF);
|
|
387
|
+
const int32_t exponent = (int32_t)((value->value.u32 >> 23) & 0xFF) - 127;
|
|
388
|
+
const int sign = (value->value.u32 & 0x80000000);
|
|
389
|
+
value->value.f32 = rc_build_float(mantissa, exponent, sign);
|
|
390
|
+
value->type = RC_VALUE_TYPE_FLOAT;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
static void rc_transform_memref_float_be(rc_typed_value_t* value) {
|
|
394
|
+
/* decodes an IEEE 754 float in big endian format */
|
|
395
|
+
const uint32_t mantissa = ((value->value.u32 & 0xFF000000) >> 24) |
|
|
396
|
+
((value->value.u32 & 0x00FF0000) >> 8) |
|
|
397
|
+
((value->value.u32 & 0x00007F00) << 8);
|
|
398
|
+
const int32_t exponent = (int32_t)(((value->value.u32 & 0x0000007F) << 1) |
|
|
399
|
+
((value->value.u32 & 0x00008000) >> 15)) - 127;
|
|
400
|
+
const int sign = (value->value.u32 & 0x00000080);
|
|
401
|
+
value->value.f32 = rc_build_float(mantissa, exponent, sign);
|
|
402
|
+
value->type = RC_VALUE_TYPE_FLOAT;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
static void rc_transform_memref_double32(rc_typed_value_t* value)
|
|
406
|
+
{
|
|
407
|
+
/* decodes the four most significant bytes of an IEEE 754 double into a float */
|
|
408
|
+
const uint32_t mantissa = (value->value.u32 & 0x000FFFFF) << 3;
|
|
409
|
+
const int32_t exponent = (int32_t)((value->value.u32 >> 20) & 0x7FF) - 1023;
|
|
410
|
+
const int sign = (value->value.u32 & 0x80000000);
|
|
411
|
+
value->value.f32 = rc_build_float(mantissa, exponent, sign);
|
|
412
|
+
value->type = RC_VALUE_TYPE_FLOAT;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
static void rc_transform_memref_double32_be(rc_typed_value_t* value)
|
|
416
|
+
{
|
|
417
|
+
/* decodes the four most significant bytes of an IEEE 754 double in big endian format into a float */
|
|
418
|
+
const uint32_t mantissa = (((value->value.u32 & 0xFF000000) >> 24) |
|
|
419
|
+
((value->value.u32 & 0x00FF0000) >> 8) |
|
|
420
|
+
((value->value.u32 & 0x00000F00) << 8)) << 3;
|
|
421
|
+
const int32_t exponent = (int32_t)(((value->value.u32 & 0x0000007F) << 4) |
|
|
422
|
+
((value->value.u32 & 0x0000F000) >> 12)) - 1023;
|
|
423
|
+
const int sign = (value->value.u32 & 0x00000080);
|
|
424
|
+
value->value.f32 = rc_build_float(mantissa, exponent, sign);
|
|
425
|
+
value->type = RC_VALUE_TYPE_FLOAT;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
static void rc_transform_memref_mbf32(rc_typed_value_t* value) {
|
|
429
|
+
/* decodes a Microsoft Binary Format float */
|
|
430
|
+
/* NOTE: 32-bit MBF is stored in memory as big endian (at least for Apple II) */
|
|
431
|
+
const uint32_t mantissa = ((value->value.u32 & 0xFF000000) >> 24) |
|
|
432
|
+
((value->value.u32 & 0x00FF0000) >> 8) |
|
|
433
|
+
((value->value.u32 & 0x00007F00) << 8);
|
|
434
|
+
const int32_t exponent = (int32_t)(value->value.u32 & 0xFF) - 129;
|
|
435
|
+
const int sign = (value->value.u32 & 0x00008000);
|
|
436
|
+
|
|
437
|
+
if (mantissa == 0 && exponent == -129)
|
|
438
|
+
value->value.f32 = (sign) ? -0.0f : 0.0f;
|
|
439
|
+
else
|
|
440
|
+
value->value.f32 = rc_build_float(mantissa, exponent, sign);
|
|
441
|
+
|
|
442
|
+
value->type = RC_VALUE_TYPE_FLOAT;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
static void rc_transform_memref_mbf32_le(rc_typed_value_t* value) {
|
|
446
|
+
/* decodes a Microsoft Binary Format float */
|
|
447
|
+
/* Locomotive BASIC (CPC) uses MBF40, but in little endian format */
|
|
448
|
+
const uint32_t mantissa = value->value.u32 & 0x007FFFFF;
|
|
449
|
+
const int32_t exponent = (int32_t)(value->value.u32 >> 24) - 129;
|
|
450
|
+
const int sign = (value->value.u32 & 0x00800000);
|
|
451
|
+
|
|
452
|
+
if (mantissa == 0 && exponent == -129)
|
|
453
|
+
value->value.f32 = (sign) ? -0.0f : 0.0f;
|
|
454
|
+
else
|
|
455
|
+
value->value.f32 = rc_build_float(mantissa, exponent, sign);
|
|
456
|
+
|
|
457
|
+
value->type = RC_VALUE_TYPE_FLOAT;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
static const uint8_t rc_bits_set[16] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
|
|
461
|
+
|
|
462
|
+
void rc_transform_memref_value(rc_typed_value_t* value, uint8_t size) {
|
|
463
|
+
/* ASSERT: value->type == RC_VALUE_TYPE_UNSIGNED */
|
|
464
|
+
switch (size)
|
|
465
|
+
{
|
|
466
|
+
case RC_MEMSIZE_8_BITS:
|
|
467
|
+
value->value.u32 = (value->value.u32 & 0x000000ff);
|
|
468
|
+
break;
|
|
469
|
+
|
|
470
|
+
case RC_MEMSIZE_16_BITS:
|
|
471
|
+
value->value.u32 = (value->value.u32 & 0x0000ffff);
|
|
472
|
+
break;
|
|
473
|
+
|
|
474
|
+
case RC_MEMSIZE_24_BITS:
|
|
475
|
+
value->value.u32 = (value->value.u32 & 0x00ffffff);
|
|
476
|
+
break;
|
|
477
|
+
|
|
478
|
+
case RC_MEMSIZE_32_BITS:
|
|
479
|
+
break;
|
|
480
|
+
|
|
481
|
+
case RC_MEMSIZE_BIT_0:
|
|
482
|
+
value->value.u32 = (value->value.u32 >> 0) & 1;
|
|
483
|
+
break;
|
|
484
|
+
|
|
485
|
+
case RC_MEMSIZE_BIT_1:
|
|
486
|
+
value->value.u32 = (value->value.u32 >> 1) & 1;
|
|
487
|
+
break;
|
|
488
|
+
|
|
489
|
+
case RC_MEMSIZE_BIT_2:
|
|
490
|
+
value->value.u32 = (value->value.u32 >> 2) & 1;
|
|
491
|
+
break;
|
|
492
|
+
|
|
493
|
+
case RC_MEMSIZE_BIT_3:
|
|
494
|
+
value->value.u32 = (value->value.u32 >> 3) & 1;
|
|
495
|
+
break;
|
|
496
|
+
|
|
497
|
+
case RC_MEMSIZE_BIT_4:
|
|
498
|
+
value->value.u32 = (value->value.u32 >> 4) & 1;
|
|
499
|
+
break;
|
|
500
|
+
|
|
501
|
+
case RC_MEMSIZE_BIT_5:
|
|
502
|
+
value->value.u32 = (value->value.u32 >> 5) & 1;
|
|
503
|
+
break;
|
|
504
|
+
|
|
505
|
+
case RC_MEMSIZE_BIT_6:
|
|
506
|
+
value->value.u32 = (value->value.u32 >> 6) & 1;
|
|
507
|
+
break;
|
|
508
|
+
|
|
509
|
+
case RC_MEMSIZE_BIT_7:
|
|
510
|
+
value->value.u32 = (value->value.u32 >> 7) & 1;
|
|
511
|
+
break;
|
|
512
|
+
|
|
513
|
+
case RC_MEMSIZE_LOW:
|
|
514
|
+
value->value.u32 = value->value.u32 & 0x0f;
|
|
515
|
+
break;
|
|
516
|
+
|
|
517
|
+
case RC_MEMSIZE_HIGH:
|
|
518
|
+
value->value.u32 = (value->value.u32 >> 4) & 0x0f;
|
|
519
|
+
break;
|
|
520
|
+
|
|
521
|
+
case RC_MEMSIZE_BITCOUNT:
|
|
522
|
+
value->value.u32 = rc_bits_set[(value->value.u32 & 0x0F)]
|
|
523
|
+
+ rc_bits_set[((value->value.u32 >> 4) & 0x0F)];
|
|
524
|
+
break;
|
|
525
|
+
|
|
526
|
+
case RC_MEMSIZE_16_BITS_BE:
|
|
527
|
+
value->value.u32 = ((value->value.u32 & 0xFF00) >> 8) |
|
|
528
|
+
((value->value.u32 & 0x00FF) << 8);
|
|
529
|
+
break;
|
|
530
|
+
|
|
531
|
+
case RC_MEMSIZE_24_BITS_BE:
|
|
532
|
+
value->value.u32 = ((value->value.u32 & 0xFF0000) >> 16) |
|
|
533
|
+
(value->value.u32 & 0x00FF00) |
|
|
534
|
+
((value->value.u32 & 0x0000FF) << 16);
|
|
535
|
+
break;
|
|
536
|
+
|
|
537
|
+
case RC_MEMSIZE_32_BITS_BE:
|
|
538
|
+
value->value.u32 = ((value->value.u32 & 0xFF000000) >> 24) |
|
|
539
|
+
((value->value.u32 & 0x00FF0000) >> 8) |
|
|
540
|
+
((value->value.u32 & 0x0000FF00) << 8) |
|
|
541
|
+
((value->value.u32 & 0x000000FF) << 24);
|
|
542
|
+
break;
|
|
543
|
+
|
|
544
|
+
case RC_MEMSIZE_FLOAT:
|
|
545
|
+
rc_transform_memref_float(value);
|
|
546
|
+
break;
|
|
547
|
+
|
|
548
|
+
case RC_MEMSIZE_FLOAT_BE:
|
|
549
|
+
rc_transform_memref_float_be(value);
|
|
550
|
+
break;
|
|
551
|
+
|
|
552
|
+
case RC_MEMSIZE_DOUBLE32:
|
|
553
|
+
rc_transform_memref_double32(value);
|
|
554
|
+
break;
|
|
555
|
+
|
|
556
|
+
case RC_MEMSIZE_DOUBLE32_BE:
|
|
557
|
+
rc_transform_memref_double32_be(value);
|
|
558
|
+
break;
|
|
559
|
+
|
|
560
|
+
case RC_MEMSIZE_MBF32:
|
|
561
|
+
rc_transform_memref_mbf32(value);
|
|
562
|
+
break;
|
|
563
|
+
|
|
564
|
+
case RC_MEMSIZE_MBF32_LE:
|
|
565
|
+
rc_transform_memref_mbf32_le(value);
|
|
566
|
+
break;
|
|
567
|
+
|
|
568
|
+
default:
|
|
569
|
+
break;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
static const uint32_t rc_memref_masks[] = {
|
|
574
|
+
0x000000ff, /* RC_MEMSIZE_8_BITS */
|
|
575
|
+
0x0000ffff, /* RC_MEMSIZE_16_BITS */
|
|
576
|
+
0x00ffffff, /* RC_MEMSIZE_24_BITS */
|
|
577
|
+
0xffffffff, /* RC_MEMSIZE_32_BITS */
|
|
578
|
+
0x0000000f, /* RC_MEMSIZE_LOW */
|
|
579
|
+
0x000000f0, /* RC_MEMSIZE_HIGH */
|
|
580
|
+
0x00000001, /* RC_MEMSIZE_BIT_0 */
|
|
581
|
+
0x00000002, /* RC_MEMSIZE_BIT_1 */
|
|
582
|
+
0x00000004, /* RC_MEMSIZE_BIT_2 */
|
|
583
|
+
0x00000008, /* RC_MEMSIZE_BIT_3 */
|
|
584
|
+
0x00000010, /* RC_MEMSIZE_BIT_4 */
|
|
585
|
+
0x00000020, /* RC_MEMSIZE_BIT_5 */
|
|
586
|
+
0x00000040, /* RC_MEMSIZE_BIT_6 */
|
|
587
|
+
0x00000080, /* RC_MEMSIZE_BIT_7 */
|
|
588
|
+
0x000000ff, /* RC_MEMSIZE_BITCOUNT */
|
|
589
|
+
0x0000ffff, /* RC_MEMSIZE_16_BITS_BE */
|
|
590
|
+
0x00ffffff, /* RC_MEMSIZE_24_BITS_BE */
|
|
591
|
+
0xffffffff, /* RC_MEMSIZE_32_BITS_BE */
|
|
592
|
+
0xffffffff, /* RC_MEMSIZE_FLOAT */
|
|
593
|
+
0xffffffff, /* RC_MEMSIZE_MBF32 */
|
|
594
|
+
0xffffffff, /* RC_MEMSIZE_MBF32_LE */
|
|
595
|
+
0xffffffff, /* RC_MEMSIZE_FLOAT_BE */
|
|
596
|
+
0xffffffff, /* RC_MEMSIZE_DOUBLE32 */
|
|
597
|
+
0xffffffff, /* RC_MEMSIZE_DOUBLE32_BE*/
|
|
598
|
+
0xffffffff /* RC_MEMSIZE_VARIABLE */
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
uint32_t rc_memref_mask(uint8_t size) {
|
|
602
|
+
const size_t index = (size_t)size;
|
|
603
|
+
if (index >= sizeof(rc_memref_masks) / sizeof(rc_memref_masks[0]))
|
|
604
|
+
return 0xffffffff;
|
|
605
|
+
|
|
606
|
+
return rc_memref_masks[index];
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/* all sizes less than 8-bits (1 byte) are mapped to 8-bits. 24-bit is mapped to 32-bit
|
|
610
|
+
* as we don't expect the client to understand a request for 3 bytes. all other reads are
|
|
611
|
+
* mapped to the little-endian read of the same size. */
|
|
612
|
+
static const uint8_t rc_memref_shared_sizes[] = {
|
|
613
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_8_BITS */
|
|
614
|
+
RC_MEMSIZE_16_BITS, /* RC_MEMSIZE_16_BITS */
|
|
615
|
+
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_24_BITS */
|
|
616
|
+
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_32_BITS */
|
|
617
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_LOW */
|
|
618
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_HIGH */
|
|
619
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_0 */
|
|
620
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_1 */
|
|
621
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_2 */
|
|
622
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_3 */
|
|
623
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_4 */
|
|
624
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_5 */
|
|
625
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_6 */
|
|
626
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_7 */
|
|
627
|
+
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BITCOUNT */
|
|
628
|
+
RC_MEMSIZE_16_BITS, /* RC_MEMSIZE_16_BITS_BE */
|
|
629
|
+
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_24_BITS_BE */
|
|
630
|
+
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_32_BITS_BE */
|
|
631
|
+
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_FLOAT */
|
|
632
|
+
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_MBF32 */
|
|
633
|
+
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_MBF32_LE */
|
|
634
|
+
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_FLOAT_BE */
|
|
635
|
+
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_DOUBLE32 */
|
|
636
|
+
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_DOUBLE32_BE*/
|
|
637
|
+
RC_MEMSIZE_32_BITS /* RC_MEMSIZE_VARIABLE */
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
uint8_t rc_memref_shared_size(uint8_t size) {
|
|
641
|
+
const size_t index = (size_t)size;
|
|
642
|
+
if (index >= sizeof(rc_memref_shared_sizes) / sizeof(rc_memref_shared_sizes[0]))
|
|
643
|
+
return size;
|
|
644
|
+
|
|
645
|
+
return rc_memref_shared_sizes[index];
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
uint32_t rc_peek_value(uint32_t address, uint8_t size, rc_peek_t peek, void* ud) {
|
|
649
|
+
if (!peek)
|
|
650
|
+
return 0;
|
|
651
|
+
|
|
652
|
+
switch (size)
|
|
653
|
+
{
|
|
654
|
+
case RC_MEMSIZE_8_BITS:
|
|
655
|
+
return peek(address, 1, ud);
|
|
656
|
+
|
|
657
|
+
case RC_MEMSIZE_16_BITS:
|
|
658
|
+
return peek(address, 2, ud);
|
|
659
|
+
|
|
660
|
+
case RC_MEMSIZE_32_BITS:
|
|
661
|
+
return peek(address, 4, ud);
|
|
662
|
+
|
|
663
|
+
default:
|
|
664
|
+
{
|
|
665
|
+
uint32_t value;
|
|
666
|
+
const size_t index = (size_t)size;
|
|
667
|
+
if (index >= sizeof(rc_memref_shared_sizes) / sizeof(rc_memref_shared_sizes[0]))
|
|
668
|
+
return 0;
|
|
669
|
+
|
|
670
|
+
/* fetch the larger value and mask off the bits associated to the specified size
|
|
671
|
+
* for correct deduction of prior value. non-prior memrefs should already be using
|
|
672
|
+
* shared size memrefs to minimize the total number of memory reads required. */
|
|
673
|
+
value = rc_peek_value(address, rc_memref_shared_sizes[index], peek, ud);
|
|
674
|
+
return value & rc_memref_masks[index];
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
void rc_update_memref_value(rc_memref_value_t* memref, uint32_t new_value) {
|
|
680
|
+
if (memref->value == new_value) {
|
|
681
|
+
memref->changed = 0;
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
memref->prior = memref->value;
|
|
685
|
+
memref->value = new_value;
|
|
686
|
+
memref->changed = 1;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs)
|
|
691
|
+
{
|
|
692
|
+
if (memrefs)
|
|
693
|
+
memset(memrefs, 0, sizeof(*memrefs));
|
|
694
|
+
|
|
695
|
+
parse->memrefs = memrefs;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
static uint32_t rc_get_memref_value_value(const rc_memref_value_t* memref, int operand_type) {
|
|
699
|
+
switch (operand_type)
|
|
700
|
+
{
|
|
701
|
+
/* most common case explicitly first, even though it could be handled by default case.
|
|
702
|
+
* this helps the compiler to optimize if it turns the switch into a series of if/elses */
|
|
703
|
+
case RC_OPERAND_ADDRESS:
|
|
704
|
+
return memref->value;
|
|
705
|
+
|
|
706
|
+
case RC_OPERAND_DELTA:
|
|
707
|
+
if (!memref->changed) {
|
|
708
|
+
/* fallthrough */
|
|
709
|
+
default:
|
|
710
|
+
return memref->value;
|
|
711
|
+
}
|
|
712
|
+
/* fallthrough */
|
|
713
|
+
case RC_OPERAND_PRIOR:
|
|
714
|
+
return memref->prior;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
void rc_get_memref_value(rc_typed_value_t* value, rc_memref_t* memref, int operand_type) {
|
|
719
|
+
value->type = memref->value.type;
|
|
720
|
+
value->value.u32 = rc_get_memref_value_value(&memref->value, operand_type);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
uint32_t rc_get_modified_memref_value(const rc_modified_memref_t* memref, rc_peek_t peek, void* ud) {
|
|
724
|
+
rc_typed_value_t value, modifier;
|
|
725
|
+
|
|
726
|
+
rc_evaluate_operand(&value, &memref->parent, NULL);
|
|
727
|
+
rc_evaluate_operand(&modifier, &memref->modifier, NULL);
|
|
728
|
+
|
|
729
|
+
switch (memref->modifier_type) {
|
|
730
|
+
case RC_OPERATOR_INDIRECT_READ:
|
|
731
|
+
rc_typed_value_add(&value, &modifier);
|
|
732
|
+
rc_typed_value_convert(&value, RC_VALUE_TYPE_UNSIGNED);
|
|
733
|
+
value.value.u32 = rc_peek_value(value.value.u32, memref->memref.value.size, peek, ud);
|
|
734
|
+
value.type = memref->memref.value.type;
|
|
735
|
+
break;
|
|
736
|
+
|
|
737
|
+
case RC_OPERATOR_SUB_PARENT:
|
|
738
|
+
/* sub parent is "-parent + modifier" */
|
|
739
|
+
rc_typed_value_negate(&value);
|
|
740
|
+
rc_typed_value_add(&value, &modifier);
|
|
741
|
+
rc_typed_value_convert(&value, memref->memref.value.type);
|
|
742
|
+
break;
|
|
743
|
+
|
|
744
|
+
case RC_OPERATOR_SUB_ACCUMULATOR:
|
|
745
|
+
rc_typed_value_negate(&modifier);
|
|
746
|
+
/* fallthrough */ /* to case RC_OPERATOR_SUB_ACCUMULATOR */
|
|
747
|
+
|
|
748
|
+
case RC_OPERATOR_ADD_ACCUMULATOR:
|
|
749
|
+
/* when modifying the accumulator, force the modifier to match the accumulator
|
|
750
|
+
* type instead of promoting them both to the less restrictive type.
|
|
751
|
+
*
|
|
752
|
+
* 18 - 17.5 will result in an integer. should it be 0 or 1?
|
|
753
|
+
*
|
|
754
|
+
* default: float is less restrictive, convert both to float for combine,
|
|
755
|
+
* then convert to the memref type.
|
|
756
|
+
* (int)((float)18 - 17.5) -> (int)(0.5) -> 0
|
|
757
|
+
*
|
|
758
|
+
* accumulator is integer: force modifier to be integer before combining
|
|
759
|
+
* (int)(18 - (int)17.5) -> (int)(18 - 17) -> 1
|
|
760
|
+
*/
|
|
761
|
+
rc_typed_value_convert(&modifier, value.type);
|
|
762
|
+
rc_typed_value_add(&value, &modifier);
|
|
763
|
+
rc_typed_value_convert(&value, memref->memref.value.type);
|
|
764
|
+
break;
|
|
765
|
+
|
|
766
|
+
default:
|
|
767
|
+
rc_typed_value_combine(&value, &modifier, memref->modifier_type);
|
|
768
|
+
rc_typed_value_convert(&value, memref->memref.value.type);
|
|
769
|
+
break;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
return value.value.u32;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
void rc_update_memref_values(rc_memrefs_t* memrefs, rc_peek_t peek, void* ud) {
|
|
776
|
+
rc_memref_list_t* memref_list;
|
|
777
|
+
rc_modified_memref_list_t* modified_memref_list;
|
|
778
|
+
|
|
779
|
+
memref_list = &memrefs->memrefs;
|
|
780
|
+
do
|
|
781
|
+
{
|
|
782
|
+
rc_memref_t* memref = memref_list->items;
|
|
783
|
+
const rc_memref_t* memref_stop = memref + memref_list->count;
|
|
784
|
+
|
|
785
|
+
for (; memref < memref_stop; ++memref) {
|
|
786
|
+
if (memref->value.type != RC_VALUE_TYPE_NONE)
|
|
787
|
+
rc_update_memref_value(&memref->value, rc_peek_value(memref->address, memref->value.size, peek, ud));
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
memref_list = memref_list->next;
|
|
791
|
+
} while (memref_list);
|
|
792
|
+
|
|
793
|
+
modified_memref_list = &memrefs->modified_memrefs;
|
|
794
|
+
if (modified_memref_list->count) {
|
|
795
|
+
do {
|
|
796
|
+
rc_modified_memref_t* modified_memref = modified_memref_list->items;
|
|
797
|
+
const rc_modified_memref_t* modified_memref_stop = modified_memref + modified_memref_list->count;
|
|
798
|
+
|
|
799
|
+
for (; modified_memref < modified_memref_stop; ++modified_memref)
|
|
800
|
+
rc_update_memref_value(&modified_memref->memref.value, rc_get_modified_memref_value(modified_memref, peek, ud));
|
|
801
|
+
|
|
802
|
+
modified_memref_list = modified_memref_list->next;
|
|
803
|
+
} while (modified_memref_list);
|
|
804
|
+
}
|
|
805
|
+
}
|